<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <title>Vlad&#x27;s Tech Blog</title>
    <link>https://vladris.com/blog/</link>
    <description></description>
    <language>en-us</language>


    <item>
      <link>https://vladris.com/blog/2026/04/04/devlog-7-longhand.html</link>
      <guid>https://vladris.com/blog/2026/04/04/devlog-7-longhand.html</guid>
      <title><![CDATA[DevLog 7: Longhand]]></title>
      <description><![CDATA[<h1>DevLog 7: Longhand</h1>

<p>I talked a bunch about Flow, the focused text editor I built during the past
couple of years. I released Flow on the MacOS App Store and on the Windows Store
and I'm pretty happy with the editing experience.</p>

<p>One thing I was still missing was a solution for long form writing. I used
Obsidian to organize my last novel, but Obsidian is a note taking/PKB tool, not
a manuscript management tool. I mentioned this when I started working on
<a href="https://vladris.com/blog/2025/03/08/devlog-1-flow.html">Flow</a>. Since then, I
learned about several other applications in the space, like
<a href="https://ulysses.app/">Ulysses</a> and <a href="https://www.dabblewriter.com/">Dabble</a>,
which are closer to what I'm imagining but still lacking in UX and
cross-platform support.</p>

<p>Now that I have a solid core editor, my next project is an editor for long form
writers. Introducing: <em>Longhand</em>.</p>

<p><img src="./screenshot.jpg" alt="Longhand screenshot"/></p>

<p>I absolutely plan to write my next book with it.</p>

<h2>Information Architecture</h2>

<p>The app uses the same side rail as Flow for modes, settings etc.</p>

<p>Unlike Flow, which is a single-file editor, Longhand works across multiple
files. I'm following the Obsidian model, where a project is simply a folder on
disk. These are split into two main categories: <em>Manuscript</em> and <em>Notes.</em> Should
be self-explanatory. Longhand allows hierarchical groupings - for example
multiple <em>chapters</em> belong to a <em>part</em>. Notes can similarly be parented. Here,
unlike Obsidian, I am not using sub-folders. That's because in a book, hierarchy
parents might contain content themselves. The novel's <em>Part 1</em> page has a title,
maybe a quote, so just sticking chapters under a <code>Part 1</code> subfolder isn't
enough. The app has a collapsible left pane to manage manuscript chapters and
notes.</p>

<p>Reading mode pulls together the whole manuscript into one view.</p>

<p>The other concept I introduced is that of <em>Tools</em>. Tools appear on the right side pane and offer various useful functionality. So far I have:</p>

<ul>
<li>Minimap - Not sure how useful this is but I really like how minimaps look so I
built one.</li>
<li>ToC - Table of Contents inferred based on hierarchy and headings, with
one-click navigation.</li>
<li>Search - Search tool with filters to scope search to manuscript or notes
only.</li>
<li>Grammar checker - Non-intrusive, revise grammar only when needed.</li>
<li>Export - I have big plans here but starting small, with basic PDF and Word
export.</li>
<li>Version history - This is a useful one. Whenever the user first edits a file
in a session, Longhand automatically saves a copy. Unhappy with the latest
revision? You can easily go back in time to an older version.</li>
</ul>

<p>I have a long list of tools to add on the backlog. For example, a tool to pin notes relevant to the chapter on the side for easy reference etc.</p>

<p>This should give you more insight on my previous <a href="https://vladris.com/blog/2026/03/22/notes-on-markdown.html">rant on
Markdown</a>. I want
to add support for comments and revisions. This is where Markdown is no longer
a great fit and I'll need to figure out how to implement these.</p>

<h2>Platform</h2>

<p>One of the biggest decisions I ended up regretting with Flow is choosing
Electron. I quickly learned Electron is a hog, the bundled browser taking up
hundreds of megabytes, way more than my modes app code. I was also disappointed
to learn Electron doesn't run on iPad. I like writing on my iPad with a Magic
Keyboard.</p>

<p>For Longhand I'm using <a href="https://v2.tauri.app/">Tauri</a>. Tauri uses the OS native
web view, for better or worse. It's a lot slimmer because of this, but I expect
cross-platform becomes more difficult targeting different web platforms. At this
point I'm willing to accept the tradeoff. Tauri is tiny! It uses Rust on the
native side and works on all platforms. More or less, iOS support is still
<q>experimental.</q> That said, I was able to get Longhand running on an iPad
simulator.</p>

<p>I'm currently focusing on the MacOS version to get a solid initial experience
out. Then Windows, like I did with Flow. Then iPad and iPhone.</p>

<h2>A Note on Coding Agents</h2>

<p>I've been more and more impressed with the capability of coding agents. When I
first started working on Flow, it was a lot of co-authoring with Copilot in VS
Code. Most of Longhand implementation was Claude CLI. Ever since Opus 4.5,
coding agents work great autonomously.</p>

<p>It also helps that I'm using the same core editor as Flow, which didn't require
a lot of changes. I did have to touch it for a couple of new features, like
multiple highlight colors. The agent did a solid job, don't get me wrong, but
those are the PRs I spend most time on since the core editor is the engine
behind all of this.</p>

<p>The full app experience includes a lot of chrome and tools which are fairly
self-contained. I believe I got the app architecture right, so tacking on tools
with Claude is very easy.</p>

<p>I wanted to implement subscriptions for Longhand. I have no experience setting
this up and was able to stand up an end-to-end sign in and subscription flow
with Supabase, Resend, and Stripe in a few hours. As I said, I am more and more
impressed with what agents can do.</p>

<p>I am also saddened by how developer-hostile Apple is. On Apple platform I must
use their APIs for any in-app payments (from which they take their 30% cut).
Getting this working took a lot longer than Stripe, with many manual steps
involved and a testing solution that doesn't quite work. As much as I love using
Apple products for their great user experience, the developer experience on the
platform was always terrible and is not getting any better.</p>

<h2>Release</h2>

<p>The first version of Longhand will be out for MacOS in the next few days. I have
a long backlog of stuff to add to it, but I have a very solid MVP.</p>
]]></description>
      <pubDate>Sat, 04 Apr 2026 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2026/03/22/notes-on-markdown.html</link>
      <guid>https://vladris.com/blog/2026/03/22/notes-on-markdown.html</guid>
      <title><![CDATA[DevLog 6: Extending Markdown]]></title>
      <description><![CDATA[<h1>DevLog 6: Extending Markdown</h1>

<p>Markdown is ubiquitous nowadays. LLMs speak Markdown. Text editors embrace
Markdown. I've been working with it both on my text editor side-project and
on my main job. Markdown is great as a lightweight, easy-to-read markup
syntax but it has its limitations. Everyone ends up working around those
limitations in one way or another, which makes it difficult to have good
interoperability.</p>

<p>The reason for this is that Markdown was originally envisioned as a
text-to-html but ended up having to support a lot more <em>stuff</em>.</p>

<p>As I mentioned in <a href="https://vladris.com/blog/2025/09/08/devlog-5-markdown-and-wysiwyg.html">Markdown and WYSIWYG</a>,
the de facto standard for Markdown is <a href="https://commonmark.org/">CommonMark</a>.
CommonMark defines the basics - bold, italics, and so on. It also defines
lists, quotes, images. But it misses a lot of fairly common formatting
elements and entities. I called out tables as an example in my previous post.
Everyone is familiar with the table syntax, but this was introduced by GitHub
as part of their <a href="https://github.github.com/gfm/">GitHub Flavored Markdown</a>
spec.</p>

<p>GFM also introduced task list items:</p>
<div class="highlight"><pre><span/><span class="k">- [x]</span> Todo 1
<span class="k">- [ ]</span> Todo 2
</pre></div>

<p>Commonly understood by parsers but not <q>standard</q>. Same with strikethrough.
This would be the <code>~~</code> markers, as in <code>~~struck~~</code>.</p>

<h2>Two Ways To Extend</h2>

<h3>Custom Syntax</h3>

<p>One way the syntax gets extended is with custom markers. The above strikethrough
is an example. There's also underline, which is commonly a single <code>~</code>, as in
<code>~underlined~</code>.</p>

<p>Footnotes are another common extension, where a footnote is specified inline via
<code>[^1]</code> and, at the bottom of the document, <code>[^1]: &lt;Footnote content&gt;</code>.</p>

<p>Math is another one, when we want to render some LaTeX-syntax math using a
library like MathJax. Inline math ends up between <code>$</code> markers and blocks end up
between <code>$$</code> markers.</p>

<p>Highlights are written with <code>==</code>, as in <code>==highlighted==</code>.</p>

<h3>Tags</h3>

<p>The other way to extend Markdown is via HTML tags. Markdown allows embedded
tags which are pass-through in the parser.</p>

<p>If we want subscript, we can write, for example, <code>H&lt;sub&gt;2&lt;/sub&gt;O</code>. A well-behaved
parser will leave <code>&lt;sub&gt;</code> and <code>&lt;/sub&gt;</code> in there as tags and let the HTML
renderer take care of them.</p>

<p>We don't have to limit ourselves to standard tags though, we can define our own
for the scenarios we want to support. This is common especially in interactive
LLM chat scenarios. The models speak some version of <q>standard</q> or commonly
accepted Markdown. If we want to enhance that to improve the end user
experience, say replace an email with a name and profile picture, we can use
middleware to inject a <code>&lt;custom-person&gt;</code>-<code>&lt;/custom-person&gt;</code> tag pair and have
the client interpret that.</p>

<h3>Tradeoffs</h3>

<p>The first extension mechanism covered keeps true to the spirit of Markdown. You
can read the plain text and <q>see</q> <code>==highlighted==</code> is a highlight. Tags are a
bit harder to parse with our eyes.</p>

<p>On the flip side, tags allows us to add rich custom extensions (think additional
attributes on the tag) while keeping the document standard-conforming. Any
parser will notice there's some custom <em>stuff</em> there, and skip over it.</p>

<h2>Rich Text Editing</h2>

<p>Both of the above work to a certain extent but neither is quite good enough for
interoperability between editors.</p>

<p>As I've been working on my text editor side-project, I'm reaching a point where
I want to go beyond the basics and implement some common editor features that
do not have a direct Markdown representation.</p>

<p>Up to this point, the extensions my editor supports are quite common: underline,
strikethrough, highlights. Now it gets more interesting. I want to add support
for multiple highlight colors.</p>

<p>What <a href="https://bear.app/">Bear</a> does, which I ended up adopting, is using a block
color emoji to define the highlight color, like <code>==ð©text==</code> to signify a green
highlight. This looks very neat and you can <q>read</q> it without a parser to
understand what it does.</p>

<p>Another option is to introduce a custom tag, like <code>&lt;highlight color="green"&gt;</code>.</p>

<p>The question is, at what point does a Markdown document stop being Markdown? If
we load the custom markup in a different Markdown editor, the most likely thing
to happen is for the <code>==ð©text==</code> to show up as a yellow highlighted <q>ð©text</q>.
If we use the tags instead, a good editor will hide the tags, and leave you with
<q>text</q>. By Markdown editor here I don't mean a plain-text editor, I mean
something like the app I'm building or any similar solution.</p>

<p>I ended up implementing the Bear solution for this, though as far as I know no
other editor support this syntax.</p>

<p>Highlights are a relatively easy problem. Here's a more complex one: comments.
A good editor should support comments, which would anchor on some text and
contain additional text rendered outside the flow of the document. How would we
represent comments in Markdown?</p>

<p>There's the custom syntax approach, like <code>[this is text]{and this is a
comment}</code>. Or maybe something like footnotes, which is another common extension.
We can add a <code>[#comment]</code> inline and store it at the end of the doc as
<code>[#comment]: ...</code>.</p>

<p>Or use tags. <code>&lt;comment text="this is the comment"&gt;and this is the
text&lt;/comment&gt;</code>. Or as a reference <code>&lt;comment refid="1"&gt;this is the
text&lt;/comment&gt;</code> and somewhere else have the</p>
<div class="highlight"><pre><span/>&lt;comments&gt;
    &lt;comment refid="1"&gt;this is the comment&lt;/comment&gt;
&lt;/comments&gt;
</pre></div>

<p>All of these are viable options but it should be pretty clear they all diverge
quite far from Markdown. Maybe the first option, with some custom bracket
combination, is the most Markdown-ish. I haven't yet decided how I will
represent comments.</p>

<p>This begs the question: is Markdown really the best format to use? An option
would be to switch my editor to a custom format that can easily support all
the features I want. This can make advanced stuff like comments easy to support
and get rid of some of the quirks Markdown has, for example the double newline
required to create a new paragraph. This would be an option but, as I said at
the beginning, Markdown is ubiquitous. I do want files created with my editor
to be easily understood by reading them, opening them in another text editor,
or sending them to an LLM.</p>

<p>So inevitably, the more features I add, the further I diverge from any common
Markdown implementation. My app's parser/renderer will be the only ones that can
properly interpret any document created with my app.</p>

<h2>Solutions</h2>

<p>The pragmatic solution I will end up implementing, regardless of what flavor I
end up choosing to represent comments, is an <q>Export to common Markdown</q>
feature. Better be explicit about it. Strip custom markup/tags and, while losing
fidelity, provide an easy way to get the document closer to the <q>standard</q>.</p>

<p>I keep putting <q>standard</q> in quotes because there is no real standard. It's
a combination of CommonMark, GFM, support for footnotes and math etc.</p>

<p>I think this is a good compromise between supporting all the features I want,
having a native document format that can still be read as plain-text/by an LLM,
and also providing a <q>standard</q> representation of it.</p>

<p>That said, I do think Markdown would benefit from a well-defined way to add
custom extensions. The format is so successful, it moved far away from <em>plain
text and HTML</em>. Dozens of text editors embraced it, AI chat embraced it, and
every endpoint brought its own additions.</p>

<p>The HTML tag pass-through was a good solution for the initial intended purpose,
but it feels like a crutch as an extensibility point. What would work better
would be a syntax akin to <code>(:&lt;extension&gt;: text)</code>. This would make it explicit
to a parser that a custom extension to the syntax is being used and let it
handle it as appropriate: discard it and keep the text only, delegate to the
extension if available, replace it with a placeholder etc. Not very different
from the HTML tags, but unlike HTML tags, this wouldn't be simply pass-through,
it would have semantic meaning to the parser. Something like this would also
make it easier for both humans and AI to reason over a document, even when the
extension interpretation is missing.</p>

<p>The proposed syntax is just an example, it doesn't have to be this, it just has
to be something everyone agrees on that meets the requirements.</p>

<p>With this, we would represent a green highlight as <code>(:highlight green: text)</code>.
Easy to read as plain text and an editor missing the extension could just render
<code>text</code>. Maybe even have some fallback to hint to the user the text is marked
but the markup is unsupported. A comment could be written as <code>(:comment "this is
the comment": text)</code>.</p>

<p>HTML tags would be used as originally intended, for custom HTML markup and not
to add features. LLMs would be able to clearly distinguish between custom
extensions and tags as the distinction would be explicit in the syntax rather
than inferred.</p>

<p>The Markdown ecosystem is extremely fragmented as of today and without an
agreed-upon solution to bring things back together it will just continue to
diverge. Custom notations like <code>~underline~</code> and <code>==ð©green==</code> will keep being
invented and supported inconsistently, while custom tags will continue to
provide non-portable extensibility. I wish we had a better way of doing this
and I'm worried we're too far down the road by now to retrofit it in.</p>
]]></description>
      <pubDate>Sun, 22 Mar 2026 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2026/01/27/jazz-an-exploration.html</link>
      <guid>https://vladris.com/blog/2026/01/27/jazz-an-exploration.html</guid>
      <title><![CDATA[Jazz: An Exploration]]></title>
      <description><![CDATA[<h1>Jazz: An Exploration</h1>

<script src="./jazz-components.min.js"/>

<p>For the past few years, I've been interested in jazz. I want to learn more about
the genre. I don't have a good ear, and I have zero musical training, which
makes this difficult.</p>

<p>I finally got around to reading Ted Gioia's <a href="https://www.goodreads.com/book/show/177539.The_History_of_Jazz">The History of
Jazz</a>.
This is an incredibly well-researched book by someone who obviously loves the
genre. I've been enjoying it, though I'm not making the most out of it myself.
The text casually mentions songs everywhere, which I need to search and listen
to. I sometimes do this, sometimes, especially if my phone isn't handy, I don't.
Many of the passages refer to music theoretical terms that I do not grasp. I
realized I need a slightly different medium to improve my study.</p>

<p>I ended up building <a href="https://vladris.com/jazz-book/">Jazz: An Exploration</a>.</p>

<h2>Something between a book and a wiki</h2>

<p>A book seems to be too linear for a topic like jazz. I don't want to break the
flow to find a song. I want a way to quickly reference a term like <em>chord</em> if
I don't understand it.</p>

<p>A wiki doesn't have a narrative thread. I can jump from article to article
though it's hard to distinguish between progress and going down some side rabbit
hole.</p>

<p>To counter my own limitations, I came up with something that sits between a book
and a wiki. The two main elements I've been exploring are <em>threads</em> and
<em>interactive elements</em>.</p>

<h3>Threads</h3>

<p>I view jazz as best explored through multiple lines. The backbone is the
history: where it originated, how it evolved. The story of the genre. A parallel
thread is the key players and innovators. For example, Miles Davis was a key
figure in cool jazz, modal jazz, fusion etc. His biography runs parallel to the
different historical eras. I call these parallel lines <em>threads</em>.</p>

<p>My exploration of jazz has a <em>history</em> thread, and a parallel <em>players</em> thread.
When the history mentions a key figure, you can switch threads to read about
the player. Or, vice versa, reading about the players in chronological order,
you can hop threads to read about the history of that era.</p>

<p>All in all I included five threads in the exploration:</p>

<ul>
<li>History: From origin until after fusion.</li>
<li>Players: Key players that influenced the genre.</li>
<li>Recordings: Genre-defining recordings, including listening guides.</li>
<li>Standards: A selection of jazz standards, with recordings by different artists
and listening guides.</li>
<li>Theory: Some music theory basics to help decode jazz.</li>
</ul>

<h3>Interactive elements</h3>

<p>The interactive elements idea is nothing new, but I personally find it very
useful. The text doesn't just mention a song, there's an embedded Apple Music
player so listening to it is one click away:</p>

<div id="player"/>

<script>JazzComponents.renderAppleMusic(document.getElementById('player'), {
    id: "1249030790?i=1249031216",
    title: "Black Lace Freudian Slip",
    artist: "RenÃ© Marie",
    country: "us"
});</script>

<p>For the music theory part, I included several interactive components.</p>

<p>Here's musical notation that can be played:</p>

<div id="notation"/>

<script>JazzComponents.renderNotation(document.getElementById('notation'), {
    notes: "C4/8 C#4/8 D4/8 D#4/8 E4/8 F4/8 F#4/8 G4/8",
    clef: "treble",
    time: "4/4",
    tempo: 140
});</script>

<p>Here's an interactive piano (multi-touch supported) for playing scales:</p>

<div id="piano"/>

<script>JazzComponents.renderPiano(document.getElementById('piano'), {
    root: "C",
    mode: "major",
    octaves: 2,
    startOctave: 4,
    interactive: true
});</script>

<p>Here's a chord player:</p>

<div id="progression"/>

<script>JazzComponents.renderProgression(document.getElementById('progression'), {
    chords: "Dm7|G7|Cmaj7",
    tempo: 100,
    beats: 4,
    loop: false,
    label: "ii-V-I in C Major"
});</script>

<p>And a drum pattern to explain rhythm:</p>

<div id="drums"/>

<script>JazzComponents.renderDrums(document.getElementById('drums'), {
    pattern: "swing",
    tempo: 120
});</script>

<p>The main theme here is to seamlessly transition between reading and listening.</p>

<h2>Implementation</h2>

<p>I used AI both to implement this and to generate the content. As a writer, I am
very much opposed to AI generating content. I would never use it and claim
authorship. I firmly believe a writer needs to use their own voice. Disclaimer
aside, in this particular case is something I'm doing for my own learning. I
know so little about jazz that it would be impossible for me to produce the
content. I'm leveraging AI as a learning tool.</p>

<p>I have two interesting anecdotes from putting together this project: embedding
the music player for the various songs, and generating content.</p>

<h3>Music player</h3>

<p>I originally tried to embed the Spotify player. Both Spotify and Apple Music
embeds rely on a track ID which uniquely identifies the song. Claude happily
hallucinated IDs for all songs mentioned. 5 of them worked out of around 250
songs referenced.</p>

<p>I tried a couple of approaches to fix this, since looking up 250 songs by hand
would take quite a while. First, I let Claude access Spotify which promptly got
us rate-limited. After a cooldown period, once I was able to access Spotify
again, I tried getting an API key to access their endpoint programmatically.
Unfortunately it seems like at the moment, Spotify wasn't allowing the creation
of new apps.</p>

<p>I decided to switch to Apple Music. This went a lot smoother, the public
endpoint Apple exposes is not as restrictive as Spotify's. Claude was able to
search for each individual song by artist and title and get the correct IDs
without getting rate-limited.</p>

<p>One issue I am aware of is it didn't do a good job when we needed a particular
recording. Jazz artists might record the same song many times. For example, a
landmark recording is Benny Goodman's Carnegie Hall recording in 1938. The
songs found on Apple Music are by the same artist and have the same title, but
they're not the ones recorded live at Carnegie Hall.</p>

<p>This issue is something that I could address in probably several ways: just
manually find the right song since the list of songs where the specific
recording matters is quite small; alternately guide Claude to better navigate
Apple Music. For now, I can live with it - I suspect my ear is not trained
enough to pick up on differences between recordings.</p>

<h3>Content generation</h3>

<p>The other interesting challenge was generating content. This was a multi-step
process. First, I started with the very high-level: What is the list of key
players we should cover? Next, for each one, generate a high-level summary,
the bullet points we need to cover. Finally, flesh out the chapter.</p>

<p>This isn't enough though! What prevents the model from hallucinating facts? I
ended up building a validation pipeline. For reach article, I had Claude extract
<em>claims</em> in the following format:</p>
<div class="highlight"><pre><span/><span class="p">{</span>
<span class="w">  </span><span class="nt">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"1.0"</span><span class="p">,</span>
<span class="w">  </span><span class="nt">"sourceFile"</span><span class="p">:</span><span class="w"> </span><span class="s2">"content/players/21-miles-davis.md"</span><span class="p">,</span>
<span class="w">  </span><span class="nt">"extractedAt"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2026-01-24T12:00:00Z"</span><span class="p">,</span>
<span class="w">  </span><span class="nt">"claims"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">      </span><span class="nt">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"players-21-miles-davis-L15-1"</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"biographical"</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"subtype"</span><span class="p">:</span><span class="w"> </span><span class="s2">"birth"</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"text"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Miles Dewey Davis III was born on May 26, 1926, in Alton, Illinois"</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"line"</span><span class="p">:</span><span class="w"> </span><span class="mi">15</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"entities"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nt">"names"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Miles Dewey Davis III"</span><span class="p">],</span>
<span class="w">        </span><span class="nt">"dates"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"1926-05-26"</span><span class="p">],</span>
<span class="w">        </span><span class="nt">"locations"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Alton, Illinois"</span><span class="p">]</span>
<span class="w">      </span><span class="p">},</span>
<span class="w">      </span><span class="nt">"verificationHint"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Miles Davis birth date birthplace"</span>
<span class="w">    </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">      </span><span class="nt">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"players-21-miles-davis-L42-2"</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"recording"</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"subtype"</span><span class="p">:</span><span class="w"> </span><span class="s2">"session"</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"text"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Kind of Blue was recorded on March 2 and April 22, 1959, at Columbia's 30th Street Studio"</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"line"</span><span class="p">:</span><span class="w"> </span><span class="mi">42</span><span class="p">,</span>
<span class="w">      </span><span class="nt">"entities"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nt">"names"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Miles Davis"</span><span class="p">],</span>
<span class="w">        </span><span class="nt">"dates"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"1959-03-02"</span><span class="p">,</span><span class="w"> </span><span class="s2">"1959-04-22"</span><span class="p">],</span>
<span class="w">        </span><span class="nt">"locations"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Columbia's 30th Street Studio"</span><span class="p">,</span><span class="w"> </span><span class="s2">"New York"</span><span class="p">],</span>
<span class="w">        </span><span class="nt">"works"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s2">"Kind of Blue"</span><span class="p">]</span>
<span class="w">      </span><span class="p">},</span>
<span class="w">      </span><span class="nt">"verificationHint"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Kind of Blue recording dates studio"</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">  </span><span class="p">]</span>
<span class="p">}</span>
</pre></div>

<p>I doubt the format itself matters much, this is what Claude itself suggested.
The key point being to extract this information.</p>

<p>Next, I had it cross-check this with Wikipedia and other web sources. In this
iteration, it read a claims file and, claim by claim, made sure there is
information to back it on the web. The prompt specifically insisted on not
relying on internal knowledge for the validation. Here's a snippet:</p>
<div class="highlight"><pre><span/>You are validating factual claims extracted from educational content about jazz
history. For each claim, you must verify it against external authoritative
sources and attach the reference. **Do NOT rely on your training dataâall
validation must come from fetched external sources.**

<span class="gu">### Why External Sources Only?</span>

This validation process exists specifically to catch hallucinations and errors.
If we allowed the model to validate claims from its own knowledge, we'd be
validating potentially hallucinated content against potentially hallucinated
knowledge. Every claim must have a fetched, citable source.

<span class="gu">### Authoritative Sources (in priority order)</span>

| Source | Best For | How to Access |
|--------|----------|---------------|
| <span class="gs">**MusicBrainz**</span> | Recording dates, personnel, releases, labels | <span class="sb">`fetch_webpage`</span> on musicbrainz.org URLs |
| <span class="gs">**Wikidata**</span> | Structured data: birth/death dates, places, identifiers | <span class="sb">`fetch_webpage`</span> on wikidata.org URLs |
| <span class="gs">**Wikipedia**</span> | Biographical details, historical context, career facts | <span class="sb">`fetch_webpage`</span> on wikipedia.org URLs |
| <span class="gs">**AllMusic**</span> | Album details, session info, personnel | <span class="sb">`fetch_webpage`</span> on allmusic.com URLs |
| <span class="gs">**Discogs**</span> | Release dates, pressings, personnel | <span class="sb">`fetch_webpage`</span> on discogs.com URLs |
| <span class="gs">**Web Search**</span> | Fallback for claims not found in above sources | Use search to find authoritative sources |
</pre></div>

<p>Running validation over the extracted claims identified several inaccurate
<q>facts.</q> Somewhere between 20-30% of claims were false. Most of these were not
egregious though - mostly dates mixed up, off by a year etc. A much small number
ended up being unverifiable.</p>

<p>Is this a foolproof method? I doubt it. I expect the model to have missed
some claims during extraction and I noticed the quality of research to vary
a lot. In some cases, it simply checked Wikipedia and if it couldn't find
something it said it is unverifiable. In other instances it did a lot more
digging, searching the web, and so on.</p>

<p>I expect accuracy to increase with multiple iterations of this: rather than a
single claim extraction pass, repeat claim extraction several times to get
better coverage. Similarly, during claim validation, attempting to validate the
same claim multiple times should yield better accuracy.</p>

<h2>Thoughts</h2>

<p>Coding models are pretty great these days. I stood up the whole project over
a single weekend. Building an interactive study guide from scratch in two days
(including the content!) is quite amazing.</p>

<p>I wonder what this means for learning. It's going to be extremely easy to have
personalized study material generated on-demand.</p>

<p>I've been enjoying the multi-threaded reading experience. Claude named it
<q>aspect-oriented learning,</q> which fits very well.</p>

<p>A good next step when I have some free time is to cleanup the code I vibed and
open-source it. It's pretty messy at the moment, but I envision something like:</p>

<ul>
<li>A compiler that takes Markdown sources.</li>
<li>A plugin system for components - The musical components I used for my Jazz
exploration being an instance of this. I can imagine many other possible
component bundles like charts and graphs, math, code etc.</li>
<li>A configurable app that can serve the compiled threads. By this I don't mean
necessarily a service, the Jazz exploration is currently served from GitHub
Pages. Rather this would be the shell that can load the compiled content and
render it. Styling, keeping track of what was read, etc. would be handled
here.</li>
</ul>

<p>Of course, the current implementation is coupled with the Jazz theme.
Generalizing will take some effort.</p>

<p>Orthogonal to this, the claim checker is also interesting and might be useful.
That can be applied to any LLM (or human) generated document.</p>

<p>All in all, this has been a very fun weekend project.</p>
]]></description>
      <pubDate>Tue, 27 Jan 2026 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2026/01/02/notes-on-advent-of-code-2025.html</link>
      <guid>https://vladris.com/blog/2026/01/02/notes-on-advent-of-code-2025.html</guid>
      <title><![CDATA[Notes on Advent of Code 2025]]></title>
      <description><![CDATA[<h1>Notes on Advent of Code 2025</h1>

<p>These are my notes on the 2025 <a href="https://adventofcode.com/">Advent of Code</a>.</p>

<p>All my solutions are on my GitHubÂ <a href="https://github.com/vladris/aoc">here</a>. And
here is the disclaimer I've been using with each post:</p>

<blockquote>
<p><strong>Disclaimer on my solutions</strong></p>

<p>I use Python because I find it easiest for this type of coding. I treat
solving these as a write-only exercise. I do it for the problem-solving bit, so
I don't comment the code &amp; once I find the solution I consider itÂ doneÂ - I donât
revisit and try to optimize even though sometimes I strongly feel like there is
a better solution. I don't even share code between part 1 and part 2 - once part
1 is solved, I copy/paste the solution and change it to solve part 2, so each
can be run independently. I also rarely use libraries, and when I do it's some
standard ones likeÂ <code>re</code>,Â <code>itertools</code>, orÂ <code>math</code>. The code has no comments and is
littered with magic numbers and strange variable names. This is not how I
usually code, rather my decadent holiday indulgence. I wasn't thinking I will
end up writing a blog post discussing my solutions so I would like to apologize
for the code being hard to read.</p>
</blockquote>

<p>Some thoughts first: this year's Advent of Code was shorter - only 12 days
instead of the usual 25 days. I also have mixed feelings about a couple of the
problems. Day 10 made me break my rule of not using external libraries. Day 12
was more of a prank. I'll get into details below.</p>

<h2>Day 1: Secret Entrance</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/1">here</a>.</p>

<p>This was a very easy problem, not worth covering.</p>

<h2>Day 2: Gift Shop</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/2">here</a>.</p>

<p>This one had potential, I was disappointed you can just count through each
number in a range and check if it's invalid.</p>

<p>I'm pretty sure there's a very efficient way to do it even for very large
ranges. E.g. between 12340000 and 12349999 there's a single invalid 12341234.
There must be a formula that yields the count of invalid numbers for an
arbitrary range just by doing the math on the range bounds + account for corner
cases. But I didn't spend the time on it since I could just check every single
number in the range.</p>

<h2>Day 3: Lobby</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/3">here</a>.</p>

<p>Another easy one - for part 1, I simply checked all combinations of 2 digits
and picked the maximum.</p>

<p>For part 2, looking at all combinations doesn't work as we need to pick 12
digits out of each number. Luckily, a greedy approach works. I split the number
into a head (initially empty), and tail (all digits) and we repeat the following
algorithm 12 times: pick the largest digits from the tail that still leaves
enough digits in the tail for us to pick 12 digits total, add it to the head,
and cut the tail at the selected digit.</p>

<p>In other words, we are guaranteed to form the largest number if we keep picking
the largest available highest-order digit.</p>

<h2>Day 4: Printing Department</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/4">here</a>.</p>

<p>Part 1 is trivial.</p>

<p>Part 2 is pretty easy too - the only <q>trick</q> is to not update the grid in-place
when removing rolls. Like a game of life simulation.</p>

<h2>Day 5: Cafeteria</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/5">here</a>.</p>

<p>Part 1 is again trivial.</p>

<p>For part 2, we want to merge overlapping ranges first, then just count the
length of each range to arrive at the solution.</p>

<h2>Day 6: Trash Compactor</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/6">here</a>.</p>

<p>In part 1, based on whether the operation is addition or multiplication, we
start with <code>0</code> or <code>1</code> then simply apply the operation (<code>+</code> or <code>*</code>) to all the
numbers in a column.</p>

<p>In part 2, we also go column by column, but we do it by digit rather than by
number. The right-to-left arrangement is a red herring - both addition and
multiplication are commutative so it doesn't matter whether we start from the
left or from the right.</p>

<h2>Day 7: Laboratories</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/7">here</a>.</p>

<p>Part 1 - we just go down row by row from the top, counting hits and splitting
the beam when we encounter a <code>^</code>:</p>
<div class="highlight"><pre><span/><span class="n">hits</span> <span class="o">=</span> <span class="mi">0</span>

<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">:</span>
    <span class="n">new_beams</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">beam</span> <span class="ow">in</span> <span class="n">beams</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">line</span><span class="p">[</span><span class="n">beam</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"^"</span><span class="p">:</span>
            <span class="n">hits</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="n">new_beams</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">beam</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
            <span class="n">new_beams</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">beam</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">new_beams</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">beam</span><span class="p">)</span>
    <span class="n">beams</span> <span class="o">=</span> <span class="n">new_beams</span>
</pre></div>

<p>Part 2 is similar, the only addition being we need to keep a running tally of
how many beams (from different timelines) are at a given position.</p>
<div class="highlight"><pre><span/><span class="n">beams</span> <span class="o">=</span> <span class="p">{</span><span class="n">lines</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="s2">"S"</span><span class="p">):</span> <span class="mi">1</span><span class="p">}</span>

<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">lines</span><span class="p">:</span> 
    <span class="n">new_beams</span> <span class="o">=</span> <span class="n">defaultdict</span><span class="p">(</span><span class="nb">int</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">beam</span> <span class="ow">in</span> <span class="n">beams</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">line</span><span class="p">[</span><span class="n">beam</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"^"</span><span class="p">:</span>
            <span class="n">new_beams</span><span class="p">[</span><span class="n">beam</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+=</span> <span class="n">beams</span><span class="p">[</span><span class="n">beam</span><span class="p">]</span>
            <span class="n">new_beams</span><span class="p">[</span><span class="n">beam</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+=</span> <span class="n">beams</span><span class="p">[</span><span class="n">beam</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">new_beams</span><span class="p">[</span><span class="n">beam</span><span class="p">]</span> <span class="o">+=</span> <span class="n">beams</span><span class="p">[</span><span class="n">beam</span><span class="p">]</span>
    <span class="n">beams</span> <span class="o">=</span> <span class="n">new_beams</span>
</pre></div>

<h2>Day 8: Playground</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/8">here</a>.</p>

<p>This was a nice graph problem. For part 1, we can compute the distance
between each pair of nodes (junction boxes), sort by distance, pick the smallest
1000 pairs and add edges between them. Now we have our final graph. The next
step is to identify all the connected components of the graph and pick the three
with the largest number of nodes.</p>

<p>For part 2, note we can't just add edges to all except the last pair of nodes in
the solution for part 1, as those two nodes might already be part of the same
component. My solution here was to also precompute the distances between nodes
then, as I add edges between them, keep track of how many connected components
we have. Instead of adding 1000 edges, we keep connecting pairs of nodes until
we are left with two connected components.</p>

<h2>Day 9: Movie Theater</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/9">here</a>.</p>

<p>Part 1 was easy, as we can just compute the area for every pair of points and
pick the largest one.</p>

<p>I found Part 2 very nice. I'm not sure I have the optimal solution, but here's
how I solved it: My initial idea was to <q>draw</q> lines between the points, then
<q>flood fill</q> the area they describe. Then we can check whether a pair of points
describes an area that is fully within the filled surface or not, in which case
it is invalid. If we do this, we can pick the largest valid area (fully within)
the filled surface.</p>

<p>The only problem with this approach is that the distances between points are
very large, so going point by point to connect the surface and fill it gets too
expensive. My solution was to scale down the grid.</p>

<p>Here's an example based on the smaller-sized sample input. The sample input is:</p>
<div class="highlight"><pre><span/>..............
.......#...#..
..............
..#....#......
..............
..#......#....
..............
.........#.#..
..............
</pre></div>

<p>We can scale this down to:</p>
<div class="highlight"><pre><span/>..#...#
.......
#.#....
.......
#...#..
.......
....#.#
</pre></div>

<p>Here's how we do it: we take the set of <code>X</code> coordinates of all points, sort it
then map \(x_0 \rightarrow 0\), \(x_1 \rightarrow 2\), \(x_2 \rightarrow 4\) etc. We
do the same for the <code>Y</code> coordinates.</p>

<p>Now connecting the points and filling the surface becomes much more tractable.
We can simply update the grid with <code>#</code>s to connect a pair of points and we can
similarly flood-fill with <code>#</code> since the surface area is significantly scaled
down. We're no longer dealing with tens of thousands of points on the grid
between two points we have to connect.</p>

<p>Once we have this, we can again iterate over each pair of points and see if the
area they describe contains any <code>.</code> (which would make the area invalid), or not.
To determine which of the valid areas is the largest, we simply need to map back
the \((x_i, y_i)\) and \((x_j, y_j)\) from our scaled down grid to the actual
coordinate values. This will give us the <q>real</q> area size and by this point we
are guaranteed the area is valid (no <code>.</code> within its bounds).</p>

<h2>Day 10: Factory</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/10">here</a>.</p>

<p>For part 1, note that pushing a button toggles a set of lights. With lights
being either <q>on</q> or <q>off</q>, the toggle is an <code>XOR</code> applied to these lights.
For each available button, we either press it or we don't. Applying <code>XOR</code>
twice simply undoes its effect. The order in which we press buttons also doesn't
matter, since <code>XOR</code> is commutative. Solving part 1, for each button, we try
pressing it and not pressing it. We keep track of the number minimum number of
presses when we reach the desired end state, which is our solution.</p>

<p>I represented the lights as a bitmask, so <code>[.##.]</code> becomes <code>0b0110</code>. Similarly,
a button that toggles <code>(0, 2, 3)</code> becomes <code>0b1101</code>.</p>

<p>Here's the full solution:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">solve</span><span class="p">(</span><span class="n">goal</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="n">tail</span><span class="p">,</span> <span class="n">presses</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">best</span>

    <span class="k">if</span> <span class="n">goal</span> <span class="o">==</span> <span class="n">state</span><span class="p">:</span>
        <span class="n">best</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">best</span><span class="p">,</span> <span class="n">presses</span><span class="p">)</span>
        <span class="k">return</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">tail</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="n">h</span> <span class="o">=</span> <span class="n">tail</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
    <span class="n">solve</span><span class="p">(</span><span class="n">goal</span><span class="p">,</span> <span class="n">state</span> <span class="o">^</span> <span class="n">h</span><span class="p">,</span> <span class="n">tail</span><span class="p">[</span><span class="mi">1</span><span class="p">:],</span> <span class="n">presses</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
    <span class="n">solve</span><span class="p">(</span><span class="n">goal</span><span class="p">,</span> <span class="n">state</span><span class="p">,</span> <span class="n">tail</span><span class="p">[</span><span class="mi">1</span><span class="p">:],</span> <span class="n">presses</span><span class="p">)</span>
</pre></div>

<p><code>goal</code> is the end state we want to reach, <code>state</code> is the current state,
initially 0. <code>tail</code> are the buttons we haven't tried pressing yet (initially
this contains all the buttons), and <code>presses</code> is the number of buttons we
pressed so far.</p>

<p>Part 2 was a lot more difficult. This is a linear optimization problem. Our
target is expressed by the joltages \({j_0, j_1, ... j_m}\). We have \(n\) buttons.
A button press increments some joltages. Let's define a matrix \(options\) such
that \(options_(button, joltage)\) is \(0\) if pressing the button \(button\) doesn't
increase the joltage \(joltage\) and \(1\) if it does.</p>

<p>Then our problem becomes:</p>

<p>Given the system of equations</p>

<p>\[\begin{bmatrix}\mathrm{options}_{0,0}&amp;\mathrm{options}_{1,0}&amp;\cdots&amp;\mathrm{options}_{n-1,0}\\\mathrm{options}_{0,1}&amp;\mathrm{options}_{1,1}&amp;\cdots&amp;\mathrm{options}_{n-1,1}\\\vdots&amp;\vdots&amp;\ddots&amp;\vdots\\\mathrm{options}_{0,m-1}&amp;\mathrm{options}_{1,m-1}&amp;\cdots&amp;\mathrm{options}_{n-1,m-1}\end{bmatrix}\begin{bmatrix}x_0\\x_1\\\vdots\\x_{n-1}\end{bmatrix}=\begin{bmatrix}j_0\\j_1\\\vdots\\j_{m-1}\end{bmatrix}\]</p>

<p>find the smallest sum \(x_0 + x_1 + ... x_{n-1}\) where all of the \(x\)s are
positive integers.</p>

<p>This is where I broke my rule of not taking dependencies on external libraries
and reached out for scipy. I used <code>milp</code> (Mixed-Integer Linear Programming):</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">solve</span><span class="p">(</span><span class="n">options</span><span class="p">,</span> <span class="n">joltage</span><span class="p">):</span>
    <span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">options</span><span class="p">)</span>
    <span class="n">matrix</span> <span class="o">=</span> <span class="p">[[</span><span class="n">options</span><span class="p">[</span><span class="n">j</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">)]</span>
         <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">joltage</span><span class="p">))]</span>

    <span class="n">res</span> <span class="o">=</span> <span class="n">milp</span><span class="p">(</span>
        <span class="n">c</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span><span class="p">,</span>
        <span class="n">constraints</span><span class="o">=</span><span class="n">LinearConstraint</span><span class="p">(</span><span class="n">matrix</span><span class="p">,</span> <span class="n">joltage</span><span class="p">,</span> <span class="n">joltage</span><span class="p">),</span>
        <span class="n">bounds</span><span class="o">=</span><span class="n">Bounds</span><span class="p">(</span><span class="n">lb</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span><span class="p">,</span> <span class="n">ub</span><span class="o">=</span><span class="p">[</span><span class="nb">max</span><span class="p">(</span><span class="n">joltage</span><span class="p">)]</span> <span class="o">*</span> <span class="n">n</span><span class="p">),</span>
        <span class="n">integrality</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">*</span> <span class="n">n</span><span class="p">,</span>
    <span class="p">)</span>

    <span class="k">return</span> <span class="nb">sum</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="nb">round</span><span class="p">(</span><span class="n">x</span><span class="p">))</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">res</span><span class="o">.</span><span class="n">x</span><span class="p">])</span>
</pre></div>

<p><code>options</code> here is our matrix of which button increments which joltages and
<code>joltage</code> is the target state.</p>

<p>We invoke <code>milp</code> with coefficients 1 (<code>c</code>), specifying the linear constraint
<code>joltage &lt;= matrix.dot(x) &lt;= joltage</code> - we want the solution to be exactly
<code>joltage</code>. The <code>bounds</code> are between 0 and maximum joltage - we can press a
button at least 0 times and as most the target joltage times. The <code>integrality</code>
parameter enforces all \(x\)s are integers.</p>

<p>This produces the optimal vector.</p>

<h2>Day 11: Reactor</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/11">here</a>.</p>

<p>The first part is easy. I implemented a <code>traverse</code> that starts from <code>you</code>
and recursively traverses all connected nodes. Whenever we hit the <code>out</code>
node we increment a running total:</p>
<div class="highlight"><pre><span/><span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>

<span class="k">def</span><span class="w"> </span><span class="nf">traverse</span><span class="p">(</span><span class="n">node</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">total</span>

    <span class="k">if</span> <span class="n">node</span> <span class="o">==</span> <span class="s2">"out"</span><span class="p">:</span>
        <span class="n">total</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">return</span>

    <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">node</span><span class="p">]:</span>
        <span class="n">traverse</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>

<span class="n">traverse</span><span class="p">(</span><span class="s2">"you"</span><span class="p">)</span>
</pre></div>

<p>The graph we need to traverse is much larger in part 2. Here, I used a 2-step
approach. First, I sorted the nodes topologically:</p>
<div class="highlight"><pre><span/><span class="n">topological_order</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">visited</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>

<span class="k">def</span><span class="w"> </span><span class="nf">dfs</span><span class="p">(</span><span class="n">node</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
        <span class="k">return</span>
    <span class="n">visited</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">neighbor</span> <span class="ow">in</span> <span class="n">graph</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="p">[]):</span>
        <span class="n">dfs</span><span class="p">(</span><span class="n">neighbor</span><span class="p">)</span>
    <span class="n">topological_order</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>

<span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
    <span class="n">dfs</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</pre></div>

<p>From these, I generated the reverse of the graph:</p>
<div class="highlight"><pre><span/><span class="n">topological_order</span><span class="o">.</span><span class="n">reverse</span><span class="p">()</span>

<span class="n">reverse_graph</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">node</span><span class="p">,</span> <span class="n">neighbors</span> <span class="ow">in</span> <span class="n">graph</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
    <span class="k">for</span> <span class="n">neighbor</span> <span class="ow">in</span> <span class="n">neighbors</span><span class="p">:</span>
        <span class="n">reverse_graph</span><span class="o">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">neighbor</span><span class="p">,</span> <span class="p">[])</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
</pre></div>

<p>With these, we can compute the number of paths between a <code>start</code> and <code>end</code>
node with:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">paths</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">):</span>
    <span class="n">paths</span> <span class="o">=</span> <span class="p">{</span><span class="n">node</span><span class="p">:</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">}</span>
    <span class="n">paths</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
    <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">topological_order</span><span class="p">[</span><span class="n">topological_order</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">start</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">:</span><span class="n">topological_order</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">end</span><span class="p">)</span><span class="o">+</span><span class="mi">1</span><span class="p">]:</span>
        <span class="n">paths</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">paths</span><span class="p">[</span><span class="n">prev</span><span class="p">]</span> <span class="k">for</span> <span class="n">prev</span> <span class="ow">in</span> <span class="n">reverse_graph</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="p">[]))</span>
    <span class="k">return</span> <span class="n">paths</span><span class="p">[</span><span class="n">end</span><span class="p">]</span>
</pre></div>

<p>The solution is:</p>
<div class="highlight"><pre><span/><span class="n">paths</span><span class="p">(</span><span class="s2">"svr"</span><span class="p">,</span> <span class="s2">"fft"</span><span class="p">)</span> <span class="o">*</span> <span class="n">paths</span><span class="p">(</span><span class="s2">"fft"</span><span class="p">,</span> <span class="s2">"dac"</span><span class="p">)</span> <span class="o">*</span> <span class="n">paths</span><span class="p">(</span><span class="s2">"dac"</span><span class="p">,</span> <span class="s2">"out"</span><span class="p">)</span>
</pre></div>

<h2>Day 12: Christmas Tree Farm</h2>

<p>Problem statement is <a href="https://adventofcode.com/2025/day/12">here</a>.</p>

<p>This last one was more of a prank in my opinion. Reading the problem statement,
it's obvious the problem explodes combinatorially: we can rotate and flip
shapes, try to fit them together in various ways, the number of each type of
shape is different for each region. We obviously can't use backtracking for
this.</p>

<p>I first started looking at the inputs to see if there is maybe some optimal
combination of shapes that simplifies things, but the fact that we get different
numbers of each shape would make this not work.</p>

<p>Is there a case in which the shapes are guaranteed to fit without us having to
do any flipping/combining? Yes, there is - each shape is in a 3x3 grid, even if
it doesn't fully cover it. For a given region, if we can fit the pieces one
after another, making each take a 3x3 spot, then we can safely ignore any
rotations or packing. In other words, if the region is large enough, we have a
trivial solution.</p>

<p>Well, it turns out a large portion of the input is trivially solved like this.
As for the rest, let's look at the reverse - is there a case in which the shapes
are guaranteed <em>not</em> to fit regardless of how we combine them? Yes, there is -
for this case, we count the exact number of points a shape takes. So</p>
<div class="highlight"><pre><span/>..#
.##
##.
</pre></div>

<p>takes 5 points, the 5 <code>#</code>. If the total number of points the shapes we want to
fit is larger than the number of points in the region, it means that regardless
of how we try to rotate and arrange our shapes, they will not fit. Well, it
turns out the rest of the input cases fall in this bucket.</p>

<p>So even though the general case explodes combinatorially and to my knowledge
there is no practical solution for it, the input cases given are all trivially
solvable as they are either way too small or large enough for us to compute the
fit without doing any work.</p>

<p>All in all, it was a fun set of problems. I am a bit bummed that this year
Advent of Code ran shorter than previous years. Problem 10 was strange, it was
the first one where I reached for scipy. Most problems I can solve without
external libraries but there was no way I was going to roll my own <code>milp</code>. And
problem 12 was straight up annoying - I spent an embarrassing amount of time to
arrive at the trivial solution. Eleven more months till the next Advent of Code!</p>
]]></description>
      <pubDate>Fri, 02 Jan 2026 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/12/07/10-years.html</link>
      <guid>https://vladris.com/blog/2025/12/07/10-years.html</guid>
      <title><![CDATA[10 Years]]></title>
      <description><![CDATA[<h1>10 Years</h1>

<p>This post marks the tenth year of my technical blog. I started in 2016, ended up
writing exactly 9 posts during that year, and made it a point to consistently
stick to that number. You are reading post #90. This will be a self-indulgent
look back at the past decade.</p>

<p>Why 9 posts per year? While sometimes I have plenty of things to write about,
other times I get busy and donât have the time. Maybe something like a post per
month wouldâve been nicer, but harder to achieve. Iâm still happy I was able to
stick to this for so long.</p>

<p>I started self-hosting the blog on my own engine, Tinkerer, which is now
archived <a href="https://github.com/vladris/tinkerer">here</a>. Tinkerer relied heavily on
<a href="https://www.sphinx-doc.org/en/master/">Sphinx</a> and
<a href="https://jinja.palletsprojects.com/en/stable/">Jinja</a>, relying on the Sphinx
plugin system to turn it into a blog. Extensions provided post metadata,
ordering and pagination, RSS-feed generation and so on. That worked well until
it didnât. Updates to Sphinx irrevocably broke things, plus Markdown was gaining
momentum - who even remembers the cumbersome ReStrctured Text syntax? I
implemented Baku, the spiritual successor to Tinkerer, and used PanDoc to
migrate my old posts from RST to Markdown.</p>

<p>Baku, which Iâm using to this day, is <a href="https://github.com/vladris/baku">here</a>.
It completely drops the Sphinx dependency and replaces Jinja with a 100 LoC
templating engine which Iâm still very proud of - my
<a href="https://github.com/vladris/baku/blob/main/baku/templating.py">VerySimpleTemplate</a>.
Lesson learned: the fewer dependencies the better.</p>

<p>Throughout the years I covered various topics I was digging into at the time.
When I started the blog in 2016, I was working on the Office C++ clients. The
very first two posts are based on a Clean Code talk I used to do (see <a href="https://vladris.com/blog/2016/01/04/clean-code-part-1.html">Clean
Code Part - 1</a> and
<a href="https://vladris.com/blog/2016/01/07/clean-code-part-2.html">Clean Code Part -
2</a>).</p>

<p>I was digging deep into modern C++ at the time. Some posts, like <a href="https://vladris.com/blog/2016/03/11/arguments-and-smart-pointers.html">Arguments and
Smart
Pointers</a>
and <a href="https://vladris.com/blog/2016/10/16/notes-on-types.html">Notes on Types</a>
provide best practices. Others covered some of my own R&amp;D. A version of the
efficient stack-allocated data structure I describe in <a href="https://vladris.com/blog/2016/04/24/abusing-maps.html">(Ab)using
Maps</a> made its way into
the Office core libraries and became a standard for applicable scenarios. The
<a href="https://vladris.com/blog/2016/10/09/composable-generators.html">Composable
Generators</a> post
became this small library that enables generator chaining in C++:
<a href="https://github.com/vladris/pipe">https://github.com/vladris/pipe</a>. This was back when generators were still an
experimental language feature.</p>

<p>Around that time, I was starting to dig into types and type systems. I wrote an
initial <a href="https://vladris.com/blog/2016/10/16/notes-on-types.html">Notes on
Types</a> post, and a
while later one covering the Idris programming language - <a href="https://vladris.com/blog/2017/07/20/idris-totality-dependent-types-proofs.html">Idris: Totality,
Dependent Types,
Proofs</a>.
Then <a href="https://vladris.com/blog/2018/01/27/notes-on-oop.html">Notes on OOP</a> and
<a href="https://vladris.com/blog/2018/09/09/clean-code-types.html">Clean Code: Types</a>,
all around the topic of types. This became my first published book, <a href="https://www.manning.com/books/programming-with-types">Programming
with Types</a> in 2019.</p>

<p>Several posts from around that time were topics that I was researching and which
made their way in the book, like <a href="https://vladris.com/blog/2018/10/13/arithmetic-overflow-and-underflow.html">Arithmetic Overflow and
Underflow</a>
and <a href="https://vladris.com/blog/2018/11/18/notes-on-encoding-text.html">Notes on Encoding
Text</a>, or
excerpts from the book once it was ready:</p>

<ul>
<li><a href="https://vladris.com/blog/2019/07/16/a-switchless-state-machine.html">A Switchless State Machine</a></li>
<li><a href="https://vladris.com/blog/2019/08/10/common-algorithms.html">Common Algorithms</a></li>
<li><a href="https://vladris.com/blog/2019/09/06/higher-kinded-types-functors.html">Higher Kinded Types: Functors</a></li>
<li><a href="https://vladris.com/blog/2019/09/07/higher-kinded-types-monads.html">Higher Kinded Types: Monads</a></li>
<li><a href="https://vladris.com/blog/2019/12/27/variance.html">Variance</a></li>
</ul>

<p>I switched jobs in 2019, going from Office to Azure and trading in C++ for data
platform architecture. My first post on the subject was <a href="https://vladris.com/blog/2019/12/08/notes-on-data-engineering.html">Notes on Data
Engineering</a>.
It was a new space for me, with plenty to learn, and during 2020 I wrote a bunch
about it:</p>

<ul>
<li><a href="https://vladris.com/blog/2020/02/01/self-serve-analytics.html">Self-Serve Analytics</a></li>
<li><a href="https://vladris.com/blog/2020/03/01/azure-data-explorer.html">Azure Data Explorer</a></li>
<li><a href="https://vladris.com/blog/2020/04/27/machine-learning-at-scale.html">Machine Learning at Scale</a></li>
<li><a href="https://vladris.com/blog/2020/11/13/data-quality-testing-patterns.html">Data Quality Testing Patterns</a></li>
<li><a href="https://vladris.com/blog/2020/11/27/changing-data-classification-through-processing.html">Changing Data Classification Through Processing</a></li>
<li><a href="https://vladris.com/blog/2021/03/12/ingesting-data.html">Ingesting Data</a>
<a href="https://vladris.com/blog/2021/09/10/machine-learning-on-azure-part-1.html">Machine Learning on Azure Part
1</a>,
<a href="https://vladris.com/blog/2021/09/17/machine-learning-on-azure-part-2.html">Part
2</a>,
and <a href="https://vladris.com/blog/2021/09/24/machine-learning-on-azure-part-3.html">Part
3</a></li>
</ul>

<p>Like the previous type rabbit hole, I ended up publishing <a href="https://www.manning.com/books/data-engineering-on-azure">Data Engineering on
Azure</a> in 2021.</p>

<p>At the same time, I switched teams again, moving from Azure back to Office to
work on <a href="https://fluidframework.com/">Fluid Framework</a> and then
<a href="https://aka.ms/loop/">Loop</a>. I wrote the first <a href="https://vladris.com/blog/2021/12/11/mental-poker.html">Mental
Poker</a> post in December
2021, while thinking through how one could implement a game over Fluid
Framework. This became an on-and-off side project which resulted into the Mental
Poker series of posts:</p>

<ul>
<li><a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">Mental Poker Part 0: An Overview</a></li>
<li><a href="https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html">Mental Poker Part 1: Cryptography</a></li>
<li><a href="https://vladris.com/blog/2023/06/04/mental-poker-part-2-fluid-ledger.html">Mental Poker Part 2: Fluid Ledger</a></li>
<li><a href="https://vladris.com/blog/2023/11/28/mental-poker-part-3-transport.html">Mental Poker Part 3: Transport</a></li>
<li><a href="https://vladris.com/blog/2024/03/16/mental-poker-part-4-actions-and-async-queue.html">Mental Poker Part 4: Actions and Async Queue</a></li>
<li><a href="https://vladris.com/blog/2024/03/22/mental-poker-part-5-state-machine.html">Mental Poker Part 5: State Machine</a></li>
<li><a href="https://vladris.com/blog/2024/04/07/mental-poker-part-6-shuffling-implementation.html">Mental Poker Part 6: Shuffling Implementation</a></li>
<li><a href="https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html">Mental Poker Part 7: Primitives</a></li>
<li><a href="https://vladris.com/blog/2024/06/24/mental-poker-part-8-rock-paper-scissors.html">Mental Poker Part 8: Rock-Paper-Scissors</a></li>
<li><a href="https://vladris.com/blog/2024/07/18/mental-poker-part-9-discard-game.html">Mental Poker Part 9: Discard Game</a></li>
<li><a href="https://vladris.com/blog/2024/10/28/mental-poker-part-10-conclusions.html">Mental Poker Part 10: Conclusions</a></li>
</ul>

<p>I wrote these over the span of two years, from early 2023 to late 2024, while
creating this open source library:
<a href="https://github.com/vladris/mental-poker-toolkit">https://github.com/vladris/mental-poker-toolkit</a>.</p>

<p>Before Mental Poker, I spent 2022 digging into computability. I always found the subject fascinating:</p>

<ul>
<li><a href="https://vladris.com/blog/2022/02/12/computability-part-1-a-short-history.html">Computability Part 1: A Short History</a></li>
<li><a href="https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html">Computability Part 2: Turing Machines</a></li>
<li><a href="https://vladris.com/blog/2022/05/20/computability-part-3-tag-systems.html">Computability Part 3: Tag Systems</a></li>
<li><a href="https://vladris.com/blog/2022/06/11/computability-part-4-conway-s-game-of-life.html">Computability Part 4: Conwayâs Game of Live</a></li>
<li><a href="https://vladris.com/blog/2022/07/06/computability-part-5-elementary-cellular-automata.html">Computability Part 5: Elementary Cellular Automata</a></li>
<li><a href="https://vladris.com/blog/2022/07/31/computability-part-6-von-neumann-architecture.html">Computability Part 6: Von Neumann Architecture</a></li>
<li><a href="https://vladris.com/blog/2022/09/02/computability-part-7-machine-implementation-practicalities.html">Computability Part 7: Machine Implementation Details</a></li>
<li><a href="https://vladris.com/blog/2022/10/14/computability-part-8-lambda-calculus.html">Computability Part 8: Lambda Calculus</a></li>
<li><a href="https://vladris.com/blog/2022/12/01/computability-part-9-lisp.html">Computability Part 9: LISP</a></li>
</ul>

<p>After wrapping up the Mental Poker toolkit, I spent 2025 implementing a text
editor and wrote several DevLog posts about it -
<a href="https://vladris.com/blog/2025/03/08/devlog-1-flow.html">Flow</a>,
<a href="https://vladris.com/blog/2025/04/04/devlog-2-formatting.html">Formatting</a>,
<a href="https://vladris.com/blog/2025/05/08/devlog-3-commanding.html">Commanding</a>,
<a href="https://vladris.com/blog/2025/08/03/devlog-4-theming-and-footguns.html">Theming and
Footguns</a>,
<a href="https://vladris.com/blog/2025/09/08/devlog-5-markdown-and-wysiwyg.html">Markdown and
WYSIWYG</a>.</p>

<p>Sometime in 2023, when GPT3 took the world by storm, I wrote another book,
<a href="https://www.amazon.com/dp/B0CLSSM8RL">Large Language Models at Work</a>. I didnât
publish excerpts on my blog as I made it freely available at
<a href="https://vladris.com/llm-book">https://vladris.com/llm-book</a>. Fun fact, the book website is also built using
Baku, just like this blog.</p>

<p>The industry moved fast, and what was state of the art in 2023 became mostly
obsolete by 2025. I reflect on that in <a href="https://vladris.com/blog/2025/09/29/agent-integration-patterns.html">Agent Integration
Patterns</a>.</p>

<p>With the holiday season coming, Iâm excited about <a href="https://adventofcode.com/">Advent of
Code</a>. Iâve been solving puzzles since its inception
and since 2023, I made it a tradition to start the year with a post covering the
past Decemberâs Advent of Code, focusing on the problems I found most
interesting.</p>

<p>Not everything requires series of posts, sometimes I write a self-contained
just-for-fun thing. Like how I implemented a <a href="https://vladris.com/blog/2025/06/08/digital-horology.html">digital pendulum
clock</a>, a solver for
an iPhone game called <a href="https://vladris.com/blog/2018/04/15/kami-2.html">Kami 2</a>,
or a solver for the game <a href="https://vladris.com/blog/2017/08/13/24.html">24</a>. Or
that time I implemented
<a href="https://vladris.com/blog/2021/12/30/timsort.html">Timsort</a> to get a better
sense of how it works.</p>

<p>The above is not a complete list of what I wrote here over the past 10 years,
rather a recap of some of the major themes. Itâs been a fun ride so far. As for
the next 10 years - who knows? I know my next post will cover Advent of Code
2025. The sky is the limit beyond that.</p>

<p>I have plenty of things I still want to cover:</p>

<ul>
<li>More on Flow - Turns out you learn a lot when you implement a text editor.
Also on Flowâs successor. Electron is too much of a hog so I started
experimenting with an editor based on Tauri, geared towards long-form writing.</li>
<li>More on AI - Weâre still evolving the ways we integrate AI into software and
thereâs plenty of learning to cover there.</li>
<li>Webdev - For the past 5 years or so, my day job had me using TypeScript,
React, and the wonderful JS ecosystem. I have many thoughts here.</li>
<li>Building product - I scratched the surface of this with <a href="https://vladris.com/blog/2021/08/12/shipping-a-feature.html">Shipping a
Feature</a>. Thereâs
a lot more to cover. I learned a lot shipping software to millions of users
while working on Office.</li>
<li>Other areas of interest, like programming languages, compilers and runtimes,
pragmatic functional programming etc.</li>
</ul>

<p>Happy holidays and see you in 2026! Thank you for reading!</p>
]]></description>
      <pubDate>Sun, 07 Dec 2025 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/09/29/agent-integration-patterns.html</link>
      <guid>https://vladris.com/blog/2025/09/29/agent-integration-patterns.html</guid>
      <title><![CDATA[Agent Integration Patterns]]></title>
      <description><![CDATA[<h1>Agent Integration Patterns</h1>

<p>A couple of years ago, when LLMs started taking off, I wrote a whole book about
how to integrate models into larger applications. I knew going in that the book
will get outdated very fast due to the speed at which the industry is moving. In
fact, a few months after I finished it, the model I used throughout the book for
code examples was deprecated by OpenAI. This broke all code samples. The API
itself changed significantly since then. I guess I could use a model to upgrade
them, but the way we use models today is already very different - simply getting
the code working again is not enough.</p>

<h2>Agents and Patterns</h2>

<p>I won't attempt another applied AI book, not at this time, but I am writing this
blog post to reflect on some of the advancements and modern ways of leveraging
models. Beyond just chat, agents are becoming more and more capable and thus
useful. I want to focus on that.</p>

<p>I also believe, at some point, we will have the equivalent of the famous Design
Patterns, but focused on creating and integrating agents. We're still early, the
technology is going to advance by a few more leaps and bounds before we can pin
some things down. Or we go singularity, in which case who cares, AI will figure
everything out for us.</p>

<p>With the caveat that things might still change dramatically, let's look at how
agents are built today and how the field advanced since I wrote <a href="https://vladris.com/llm-book/">Large Language
Models at Work</a>.</p>

<h2>LLMs @ Work Teardown</h2>

<p>Here's the table of contents of my now quite stale book:</p>

<ol>
<li><em>A New Paradigm</em> - Mostly introducing what was then a very new and emerging
field.</li>
<li><em>Large Language Models</em> - Covering the basics - models, tokens, API calls
and responses.</li>
<li><em>Prompt Engineering</em> - Discussing prompt creation and tuning.</li>
<li><em>Learning and Tuning</em> - Covering in-prompt, N-shot learning and fine tuning.</li>
<li><em>Memory and Embeddings</em> - Going over context limitations and memory
implementations.</li>
<li><em>Interacting with External Systems</em> - About function calling.</li>
<li><em>Planning</em> - Multi-turn execution of a plan - remember this was written before
reasoning models and agents were the norm.</li>
<li><em>Safety and Security</em> - Pretty self-explanatory.</li>
<li><em>Frameworks</em> - Talking about LangChain and Semantic Kernel.</li>
<li><em>Closing Thoughts</em> - Again, self-explanatory. GPT4 was the new hot model when
I wrapped up the book.</li>
</ol>

<p>Looking back at this, it's quite impressive how much has changes since.</p>

<p>Starting with Chapter 2, the correct term today is <em>foundational model</em>, the large models are multi-model, not limited to language.</p>

<p>Prompt engineering (Chapter 3) fell out of favor, the modern term is <em>context
engineering</em>, which is a superset of that: it's not only about the wording of
the prompt we give the model, but all the other things we stuff into its context
window - relevant instructions, documents, available tools - to produce the
optimal response.</p>

<p>My Chapter 4 was called <em>Learning and Tuning</em>. I think a better name would be
<em>In-context Learning vs Tuning.</em> This is still an interesting debate, where the
different approaches work better for different scenarios. To quickly summarize:
if you want your model to do <em>X</em>, do you craft a solid prompt or fine-tune it?
The tradeoff is there's only so much you can do with a prompt vs. fine-tuning is
expensive and you have to redo it for every new foundational model. An
interesting deciding factor is the complexity of <em>X</em>. How much domain knowledge
does <em>X</em> require? How divergent are your expected answers from what the model
tends to output?</p>

<p><em>Memory</em> (Chapter 5) is a very interesting topic. For one, models today have much
larger context windows and they keep growing, so for a lot of small-scale
scenarios, this might be a non-issue. E.g. you can stuff a whole novel into the
context, something that wasn't possible two years ago. Industry leaders are now
offering memory built into their chat experiences, so I wouldn't be surprised if
in the near future memory gets abstracted away and handled underneath the API.
For the cases where we do have too much data to fit into the context, handling
this is now part of the <em>context engineering</em> discipline - determining what is
relevant, retrieving it, and putting it into the context.</p>

<p><em>Interacting with External Systems</em> (Chapter 6), is the fastest moving. This is no
surprise, as model interactions with side effects produce the most value. When I
started writing the book, there was no standardized function calling in the
OpenAI API. You had to <del>prompt</del> context engineer the model into telling it
what it can do and give it some examples of JSON functions calls. Before I got
to Chapter 6, OpenAI introduced functions as part of the API. Nowadays MCP is
the standard, providing complex capabilities to models. I will talk more at
length about this below.</p>

<p>Chapter 7 was about <em>Planning</em>. Multi-turn execution was pretty novel two years
ago but today in underpins all agentic workflows.</p>

<p><em>Safety and Security</em> (Chapter 8) remains a concerns. The attack surface only
grew. Two years ago, one of the biggest concerns was prompt leaking - an
attacker stealing your carefully crafted prompt. Today, with multi-turn
execution and MCP tools, the attack surface and opportunities for data exfil is
significantly larger.</p>

<p>As for <em>Frameworks</em> (Chapter 9), they kind of fell out of favor lately. As the
major players are pulling more capabilities within their APIs and models are
becoming smarter, generic frameworks are becoming maybe less popular.</p>

<p>As I wrote at the start of this post, if the field eventually slows down, there
will be plenty of opportunity to create frameworks capturing the latest patterns
and formalizing them into easy-to-use systems. But we're not there yet. After
this whirlwind review of how my last book is not so much relevant today, let me
talk a bit about the state of the art. This is going to be less of a <em>how to</em>,
more of a top of mind.</p>

<h2>Agent Engineering</h2>

<p>The biggest leap over the past two years has been giving model-based solutions a
lot more autonomy. An <em>agent</em> is usually doing multi-turn work, with a plethora
of tools at its disposal. A key learning was that new models provide such giant
leaps in capabilities that today's scaffolding need to accommodate for that,
which we call <em>model-forward</em> engineering. I'll cover these and a few other
concepts below.</p>

<h3>MCP</h3>

<p>The Model Context Protocol introduced by Anthropic provides a <q>standard</q> way of
capability providers to advertise their capabilities to a model and, vice-versa,
a common way for models to invoke tools. While MCP is not an official standard,
the fact that both Anthropic and OpenAI embraced it made it the de-facto
standard in the industry.</p>

<p>Whatever service you build, if it can <em>speak</em> MCP, agents can use it.</p>

<p>If you are building an agent, there's now a standard way to tell it what are all
the various tools it can use via MCP.</p>

<p>I expect very broad adoption of MCP. Most service will support this and you
would be missing out if you're building a service that wouldn't.</p>

<p>If you're building an agent, you'd want to supply its tools via MCP.</p>

<p>The part that I find most interesting is specialized agents exposing their
capabilities via MCP to other agents.</p>

<h3>Multi-Turn Workflows</h3>

<p>In the world of agents, multi-turn is the norm. There are few <q>serious</q> jobs you
can achieve with a single model call. The model will either ask for a tool call,
revise its plan, or even prompt the user for input.</p>

<p>Tool use is the easiest to solve: you offer the model the buffet of MCP tools
available, it responds by describing a function invocation, your code runs the
function and gives it the response.</p>

<p>Plan revisions are more interesting: with a multi-turn agent, the agent should
usually starts by creating a to-do list, then go through it turn by turn. What
happens when new information causes the plan to change? What is the right
combination of prompt, tuning, context that will make the model realize <q>oh, I'm
going down the wrong path, let me step back and try something else</q>?</p>

<p>Prompting the user for input is another very interesting one. Here I am not
talking about permissions. I've been using a lot of coding agents which, for
security reasons, prompt you before running bash commands etc. I'm talking about
the model realizing it needs some more input from you, stopping, and asking you
a clarifying question. I've rarely seen this done well with existing agents, I
think the field is ripe for opportunity and I'm looking forward to advancements
here. As a concrete example, coding agents are still writing at a junior
engineer level. I would much prefer them to stop early and ask clarifying
questions rather than doing odd things to get things to work. I also realize
this is a very hard problem.</p>

<p>The bottom-line, as we're talking about agents, is you will probably need a
bunch of code to support long-running, multi-turn workflows.</p>

<h3>Tactical Fine-Tuning</h3>

<p>Fine-tuning is taking a pre-trained model and teaching it some new stuff in the
form of prompts and expected replies. This works well for domain-specific tasks,
but it has some important trade-offs.</p>

<p>One trade-off is the fact that you'll have to fine-tune any new foundational
model you'll upgrade to. Fine-tuning is not cheap, it's an involved process, and
as new models come out quite often, there's an ongoing tax to pay to have a
bleeding-edge fine-tuned model ready to go.</p>

<p>An even bigger trade-off is a fine-tuned model will behave differently than an
<q>off-the-shelf</q> one. In a complex system, users might expect similar behavior
across surfaces but if one of the surfaces behaves differently the overall
experience will seem off. The way to mitigate this is to use <em>multi-agent
workflows</em>.</p>

<h3>Multi-Agent Workflows</h3>

<p>The concept of <em>multi-agent workflows</em> is what got me to write this post. We
looked at MCP, multi-turn, fine-tuning - the combination of these is
mind-bending. With the state of the art, an ideal agent implementation has the
following ingredients:</p>

<ul>
<li>Specialized agents fine-tuned on specific tasks.</li>
<li>Having these specialized agents implement the MCP protocol as servers.</li>
<li>An <q>entry-point</q> agent that can leverage these other specialized agents via
MCP.</li>
</ul>

<p>This idea is what got me thinking of design patterns and what those mean in the
AI world. It's a very interesting horizontal scaling concept - rather than
having a one-size-fits-all solution, have a bunch of specialists ready and an
entry point that can leverage them as needed.</p>

<p>Coincidentally, I was procrastinating writing this blog post for a week or so as
Anthropic just announced Claude Code supports <q>subagents</q>, one specializing in
code review, on specializing in debugging etc.</p>

<p>I'm positive we're entering the era of horizontal scaling where a solution will
involved a set of specialized agents rather than a <q>know-it-all</q>.</p>

<h3>Model-Forward</h3>

<p>This is a very interesting concept which means <em>How can we write software that
doesn't incur a tax when the new model comes out, rather it gets better as model
capabilities improve?</em></p>

<p>The hard-learned lesson here was that, after building frameworks, scaffolding,
prompts, and sinking a ton of engineering cost into an AI-powered solution, when
the new model came out, it could do all (most?) of that stuff out-of-the-box, no
crutches needed. Model-forward design is about future-proofing and thinking a
move ahead.</p>

<p>Can we build solutions that will just get better as the models get better?
Fine-tuning is a controversial example of this - it's costly and different, and
maybe a new, smarter model can do whatever we want to achieve without
fine-tuning.</p>

<p>Predicting the future is impossible, so what <em>can</em> we do to be model-forward?
What we can do is offload more of the work to the model. The smarter it gets,
the more it can do for us. We can give it more tools, better context, and let it
do its thing.</p>

<p>The key point behind model-forward development is to focus less on complex
scaffolding around model workflows and more on giving the model the tools it
needs and letting it work. Rather than creating a complex, multi-step
orchestration, just hand the model the right context, MCPs available, and listen
to its response.</p>

<h2>Summary</h2>

<p>In this post I looked at the analogy between AI model integration patterns and
the classic Design Patterns. I also did a teardown of my Large Language Models
at Work book, and looked at some of the emerging patterns:</p>

<ul>
<li>MCP as a standard.</li>
<li>Multi-turn as the norm.</li>
<li>Fine-tuning for specialized tasks.</li>
<li>Multiple agents working together.</li>
<li>Future-proofing with a model-forward approach.</li>
</ul>

<p>No book for now, and not any time soon. I'll either write a book on how to use
AI when we reach stable state, or we pass the event horizon and AI will write
the book much better than I ever could. I've been refocusing on writing fiction
lately.</p>
]]></description>
      <pubDate>Mon, 29 Sep 2025 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/09/08/devlog-5-markdown-and-wysiwyg.html</link>
      <guid>https://vladris.com/blog/2025/09/08/devlog-5-markdown-and-wysiwyg.html</guid>
      <title><![CDATA[DevLog 5: Markdown and WYSIWYG]]></title>
      <description><![CDATA[<h1>DevLog 5: Markdown and WYSIWYG</h1>

<p>In this post I want to cover one of the foundational features of
<a href="https://saturn9.studio/flow/">Flow</a>: its Markdown handling. I will not show a
lot of code, because most of it is boring parsing code and special-case
handling.</p>

<p>Different editors tackle Markdown in different ways. Some support a subset of
Markdown formatting on insertion, but don't preserve any markup. For example,
typing a <code>*</code> would toggle Italics on then, once the user types the closing <code>*</code>,
not only are Italics toggled off, but both <code>*</code> markups are removed from the
document. This is the behavior of editors that don't natively support Markdown.</p>

<p>Other editors support Markdown natively, like some of the apps that inspired
Flow - <a href="https://obsidian.md/">Obsidian</a> and <a href="https://bear.app">Bear</a>. The
problem with these apps is that Markdown has its own quirks which impact the
overall authoring experience. One simple example is handling of paragraphs: in
Markdown, a new paragraph starts after two newline characters. A single newline
doesn't affect the rendered document.</p>

<p>For Flow, I wanted to fully support Markdown, but also hide some of its quirks
from the user. If the user is not familiar with it at all, they should still be
able to intuitively use the app and have the best possible experience.</p>

<h2>Pre- and post- processing</h2>

<p>Flow uses pure Markdown and can load and save <code>.md</code> files. To smoothen things
out, the first thing it does when loading a document is convert it into a series
of paragraphs by handling some of the whitespace particularities of Markdown.</p>

<p>It converts a piece of text like the following</p>
<div class="highlight"><pre><span/>This is considered a single
paragraph in Markdown even though each
line ends with a newline character.

* This is a list item
* This is another list item
</pre></div>

<p>into something like</p>
<div class="highlight"><pre><span/>&lt;p&gt;This is considered a single paragraph in Markdown even though each line ends with a newline character.&lt;/p&gt;
&lt;p&gt;* This is a list item&lt;/p&gt;
&lt;p&gt;* This is another list item&lt;/p&gt;
</pre></div>

<p>The above is just to illustrate the type of transformation, we don't go straight
to <code>&lt;p&gt;</code> HTML elements, rather these are ProseMirror paragraphs.</p>

<p>The preprocessor is fairly simple, stripping single newlines where appropriate,
handling whitespace at the end of lines etc. It is also aware of lists,
codeblocks and block quotes, which have different rules. For example, a
codeblock is a single entity regardless of how many consecutive newlines appear
in its content.</p>

<p>The preprocessor runs when opening a new file. Conversely, the postprocessor
runs on save and converts the ProseMirror document back to Markdown by doubling
newlines where appropriate.</p>

<p>These are implemented by two functions:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">markdownToDoc</span><span class="p">(</span><span class="nx">markdown</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">ProseMirrorNode</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="cm">/* ... */</span>
<span class="p">}</span>

<span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">docToMarkdown</span><span class="p">(</span>
<span class="w">    </span><span class="nx">doc</span><span class="o">:</span><span class="w"> </span><span class="kt">ProseMirrorNode</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">MarkdownSerializationResult</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="cm">/* ... */</span>
<span class="p">}</span>
</pre></div>

<p>The <code>MarkdownSerializationResult</code> is defined as:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">interface</span><span class="w"> </span><span class="nx">MarkdownSerializationResult</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">markdownText</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">positionMap</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">processedPos</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The first function takes a Markdown string as input and creates the ProseMirror document (returning the root node).</p>

<p>The serialization function takes the document and returns the Markdown as a
string. In addition, it also returns a mapping from position in the Markdown
string back into the document. That is used by the parser, which we'll look at
below. First, let's look at the internal document representation.</p>

<h2>Internal representation</h2>

<p>ProseMirror allows for rich document schemas. In fact, the <a href="https://github.com/ProseMirror/prosemirror-markdown">ProseMirror Markdown
plugin</a> can translate a
Markdown document into its HTML representation and vice-versa, where a paragraph
of text becomes a <code>&lt;p&gt;</code> element, a list becomes an <code>&lt;ol&gt;</code> or <code>&lt;ul&gt;</code> consisting
of multiple <code>&lt;li&gt;</code> elements, and so on.</p>

<p>I did not use this plugin because it strips the markup during conversion. I
wanted to leave all the markdown in the document. To achieve this, Flow uses a
very simple document schema consisting exclusively of paragraphs which translate
to <code>&lt;p&gt;</code> elements. All styling is done via decorations. I talked about
ProseMirror <a href="https://prosemirror.net/docs/ref/#view.Decorations">decorations</a> in
previous posts, but to recap, at a high level, decorations add attributes to a
range of text. If my paragraph is <code>There are *italics* in this sentence</code>, we can
add a decoration from the starting <code>*</code> to the closing <code>*</code>. The rendered HTML
will look something like this <code>&lt;p&gt;There are &lt;span&gt;*italics*&lt;/span&gt; in this
sentence</code>. The <code>&lt;span&gt;</code> will have whatever attributes we want to attach to it.</p>

<p>The document schema is just:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">docSchema</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Schema</span><span class="p">({</span>
<span class="w">    </span><span class="nx">nodes</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">doc</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">content</span><span class="o">:</span><span class="w"> </span><span class="s2">"block+"</span><span class="w"> </span><span class="p">},</span>
<span class="w">        </span><span class="nx">paragraph</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">group</span><span class="o">:</span><span class="w"> </span><span class="s2">"block"</span><span class="p">,</span>
<span class="w">            </span><span class="nx">content</span><span class="o">:</span><span class="w"> </span><span class="s2">"inline*"</span><span class="p">,</span>
<span class="w">            </span><span class="nx">attrs</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">default</span><span class="o">:</span><span class="w"> </span><span class="s2">"paragraph"</span><span class="w"> </span><span class="p">},</span>
<span class="w">                </span><span class="nx">widgetId</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">default</span><span class="o">:</span><span class="w"> </span><span class="kt">null</span><span class="w"> </span><span class="p">},</span>
<span class="w">            </span><span class="p">},</span>
<span class="w">            </span><span class="nx">toDOM</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">return</span><span class="w"> </span><span class="p">[</span>
<span class="w">                    </span><span class="s2">"p"</span><span class="p">,</span>
<span class="w">                    </span><span class="p">{</span>
<span class="w">                        </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="nx">node</span><span class="p">.</span><span class="nx">attrs</span><span class="p">.</span><span class="kr">type</span><span class="p">,</span>
<span class="w">                        </span><span class="nx">widgetId</span><span class="o">:</span><span class="w"> </span><span class="kt">node.attrs.widgetId</span><span class="p">,</span>
<span class="w">                    </span><span class="p">},</span>
<span class="w">                    </span><span class="mf">0</span><span class="p">,</span>
<span class="w">                </span><span class="p">];</span>
<span class="w">            </span><span class="p">},</span>
<span class="w">        </span><span class="p">},</span>
<span class="w">        </span><span class="nx">text</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">group</span><span class="o">:</span><span class="w"> </span><span class="s2">"inline"</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">},</span>
<span class="p">});</span>
</pre></div>

<p>While the schema of Flow documents is simple, consisting of just paragraph
nodes, a lot happens at runtime to properly decorate the document.</p>

<h2>Markdown processing</h2>

<p>Flow uses <code>markdown-it</code> internally to parse the Markdown document and decorate
it for rendering. There's quite a lot of parsing logic, and since this is one of
the core capabilities of the app, I have a lot of tests around it. Properly
parsing Markdown is not easy!</p>

<p>I mentioned above that <code>There are *istalics* in this sentence</code> roughly
translated to <code>&lt;p&gt;There are &lt;span&gt;*italics*&lt;/span&gt; in this sentences&lt;/p&gt;</code>. To be
more precise, this translates into <code>&lt;p&gt;There are &lt;span class="em markup
hide-markup"&gt;*&lt;/span&gt;&lt;span class="em"&gt;italics&lt;/span&gt;&lt;span class="em markup
hide-markup"&gt;*&lt;/span&gt; in this sentences&lt;/p&gt;</code>.</p>

<p>The parser adds the <code>markup</code> and <code>hide-markup</code> decorations around the <code>*</code>s and
the <code>em</code> around the whole thing. ProseMirror maps these to the right spans on
render. We're also aware of the cursor position: if the cursor is within the
range of the decoration, we tag the markup with <code>show-markup</code> instead of
<code>hide-markup</code>.</p>

<p>Then everything is CSS: we simply get the <code>em</code> class to be italicized, <code>markup</code>
to be muted, <code>hide-markup</code> to be hidden etc. That's for the standard editor
mode. When we switch Flow to Source mode, both <code>hide-markup</code> and <code>show-markup</code>
are visible.</p>

<p>Here is where the <code>positionMap</code> comes in handy. Our ProseMirror-to-Markdown
conversion returns a <code>string</code> and a mapping. We briefly looked at this above:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">interface</span><span class="w"> </span><span class="nx">MarkdownSerializationResult</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">markdownText</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">positionMap</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">processedPos</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">docToMarkdown</span><span class="p">(</span><span class="nx">doc</span><span class="o">:</span><span class="w"> </span><span class="kt">ProseMirrorNode</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="cm">/* ... */</span>
<span class="p">}</span>
</pre></div>

<p>The reason we need this mapping is we don't only convert the document from a
ProseMirror schema to a Markdown string on save, but also to parse it and add
decorations. When we parse the Markdown and find positions where we need to add
decorations, we need to map these back to positions in the ProseMirror
document. These aren't exactly identical.</p>

<h3>Positions</h3>

<p>A quick side-note on positions: in ProseMirror, when indexing by position, we
need to account for non-text nodes (paragraphs in our case). A ProseMirrorNode
that is not a leaf text node has a <q>before</q> position and an <q>after</q> position.
This offsets things, so without maintaining a <code>positionMap</code> we end up indexing
the wrong document fragments. During serialization via <code>docToMarkdown()</code>, we not
only produce the Markdown string, but also track offsets to account for this.</p>

<h3>Lists</h3>

<p>The story is simple for basic markup. It gets a bit more complex for things like
lists. Because I wanted to Flow to have a WYSIWYG experience, I'm using
single-line lists. That is, each list item gets converted to a separate
paragraph inside the document schema. We also want to preserve the markup, so
for an unordered list, if the cursor is on it, we want to show the <code>*</code> markup.
If the cursor is on a different line, then we want to hide the <code>*</code> markup but
show the usual â¢ symbol.</p>

<p>For numbered lists, we also need to extract the number and make it available an
attribute for rendering, since ultimately lists don't translate to <code>&lt;ol&gt;</code>,
<code>&lt;ul&gt;</code>, and <code>&lt;li&gt;</code> elements, rather to <code>&lt;p&gt;</code> elements.</p>

<h3>Plugins</h3>

<p>The Markdown parsing library Flow is using, <code>markdown-it</code>, has its own plugin
system, which allows us to extend the parser with custom syntax. For example,
underlying with <code>~</code> is done with a plugin.</p>

<h3>Widgets</h3>

<p>Some elements, like code blocks and images, are represented as UI widgets in the
editor (unless in Source mode). The parser adds special decorations for these
such that, if widgets are available, we can completely hide the content and
instead inject a UI widget in the canvas.</p>

<p>I will cover widgets in detail in a future post, as they are not as interesting
from the Markdown parsing perspective, but do have a lot of code behind.</p>

<h3>Tables</h3>

<p>Flow does not support tables yet. The <a href="https://commonmark.org/">CommonMark</a> spec
does <u>not</u> include tables. Tables are an extension introduced by the <a href="https://github.github.com/gfm/">GitHub
Flavored Markdown</a> spec. I will probably end up
implementing support as specified by GitHub.</p>

<p>The reason I didn't make this part of the MVP is that tables are not critical
for creative writing. That said, as I'm using Flow to author blog posts like the
one you are reading now, I will need support for both tables and equations.</p>

<h3>Conclusion</h3>

<p>I would've very much preferred not to get into the business of parsing Markdown,
as Markdown nowadays is quite complex, which makes custom parsing logic
error-prone. That said, I couldn't find a better solution for my requirements,
namely:</p>

<ul>
<li>Load and save Markdown.</li>
<li>Provide a WYSIWYG authoring experience, which includes hiding/showing the
markup as needed.</li>
</ul>

<h2>Summary</h2>

<p>In this post I covered how Flow implements a Markdown WYSIWYG authoring
experience:</p>

<ul>
<li>Pre- and post- processing the Markdown document into a simple ProseMirror
schema.</li>
<li>The document schema, which consists of paragraphs and decorations.</li>
<li>A custom Markdown-parser based on <code>markdown-it</code> that parses the document and
adds decorations.</li>
<li>Lists, widgets etc. require special handling.</li>
</ul>

<p>This post was written with Flow. Try it out <a href="https://saturn9.studio/flow/">here</a>.</p>
]]></description>
      <pubDate>Mon, 08 Sep 2025 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/08/03/devlog-4-theming-and-footguns.html</link>
      <guid>https://vladris.com/blog/2025/08/03/devlog-4-theming-and-footguns.html</guid>
      <title><![CDATA[DevLog 4: Theming and Footguns]]></title>
      <description><![CDATA[<h1>DevLog 4: Theming and Footguns</h1>

<p>This is going to be a fun post! First, I want to show how I implemented theming
for Flow. With its focus on providing an inspiring environment, theming was
min-bar for the app. Fortunately, implementing theming is fairly
straight-foward. Until it isn't. In the first part I'll go over how I gave the
Electron app its unique look and feel. In the second part, I'll cover the
strange snag I hit.</p>

<h2>Theming</h2>

<p>Making something themeable in the web world is easy with CSS variables:</p>
<div class="highlight"><pre><span/><span class="p">:</span><span class="nd">root</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nv">--color-bg-primary</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-bg-secondary</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-bg-tertiary</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>

<span class="w">    </span><span class="nv">--color-fg-primary</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-fg-secondary</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-fg-accent</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>

<span class="w">    </span><span class="c">/* ... */</span>
<span class="p">}</span>

<span class="p">.</span><span class="nc">latte-theme</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nv">--color-bg-primary</span><span class="p">:</span><span class="w"> </span><span class="mh">#f9f5f0</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-bg-secondary</span><span class="p">:</span><span class="w"> </span><span class="mh">#e6dfd3</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-bg-tertiary</span><span class="p">:</span><span class="w"> </span><span class="mh">#f0ebe0</span><span class="p">;</span>

<span class="w">    </span><span class="nv">--color-fg-primary</span><span class="p">:</span><span class="w"> </span><span class="mh">#5a4534</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-fg-secondary</span><span class="p">:</span><span class="w"> </span><span class="mh">#7a6b4f</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-fg-accent</span><span class="p">:</span><span class="w"> </span><span class="mh">#c74343</span><span class="p">;</span>

<span class="w">    </span><span class="c">/* ... */</span>
<span class="p">}</span>
</pre></div>

<p>The <code>:root</code> style will provide the defaults while subsequent classes can
override it. In the above example, <code>.latte-theme</code> is a fragment of the app's
Latte theme.</p>

<p>On first boot, before the user can configure the theme, I want the app to
respect the operating system's dark mode. We can do this with the
<code>prefers-color-scheme: dark</code> media query:</p>
<div class="highlight"><pre><span/><span class="p">:</span><span class="nd">root</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nv">--color-bg-primary</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-bg-secondary</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-bg-tertiary</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>

<span class="w">    </span><span class="nv">--color-fg-primary</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-fg-secondary</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>
<span class="w">    </span><span class="nv">--color-fg-accent</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>

<span class="w">    </span><span class="c">/* ... */</span>

<span class="w">    </span><span class="err">@media</span><span class="w"> </span><span class="err">(</span><span class="n">prefers-color-scheme</span><span class="p">:</span><span class="w"> </span><span class="n">dark</span><span class="p">)</span><span class="w"> </span><span class="err">{</span>
<span class="w">        </span><span class="o">--</span><span class="kc">color</span><span class="o">-</span><span class="n">bg-primary</span><span class="o">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>
<span class="w">        </span><span class="nv">--color-bg-secondary</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>
<span class="w">        </span><span class="nv">--color-bg-tertiary</span><span class="p">:</span><span class="w"> </span><span class="mh">#000</span><span class="p">;</span>

<span class="w">        </span><span class="nv">--color-fg-primary</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
<span class="w">        </span><span class="nv">--color-fg-secondary</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>
<span class="w">        </span><span class="nv">--color-fg-accent</span><span class="p">:</span><span class="w"> </span><span class="mh">#fff</span><span class="p">;</span>

<span class="w">        </span><span class="c">/* ... */</span>
<span class="w">    </span><span class="p">}</span>
<span class="err">}</span>
</pre></div>

<p>With this, on first boot the app should use the <q>dark mode</q> colors if the OS is set to dark mode.</p>

<p>Now all this happens on the render thread. Electron boots up fairly fast, but
users might still see a blank window for an instant between the time the main
process has started but the render processes hasn't finished booting. For that
case, I wanted the blank window to still respect the OS setting, otherwise when
in dark mode, users might see a flashing white window. That's because Electron's
default background color is white.</p>

<p>The following code sets up the main window:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">mainWindow</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">BrowserWindow</span><span class="p">({</span>
<span class="w">  </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="kt">1200</span><span class="p">,</span>
<span class="w">  </span><span class="nx">height</span><span class="o">:</span><span class="w"> </span><span class="kt">800</span><span class="p">,</span>
<span class="w">  </span><span class="nx">minWidth</span><span class="o">:</span><span class="w"> </span><span class="kt">300</span><span class="p">,</span>
<span class="w">  </span><span class="nx">minHeight</span><span class="o">:</span><span class="w"> </span><span class="kt">400</span><span class="p">,</span>
<span class="w">  </span><span class="nx">titleBarStyle</span><span class="o">:</span><span class="w"> </span><span class="s2">"hiddenInset"</span><span class="p">,</span>
<span class="w">  </span><span class="nx">backgroundColor</span><span class="o">:</span><span class="w"> </span><span class="kt">nativeTheme.shouldUseDarkColors</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"#000"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"#fff"</span><span class="p">,</span>
<span class="w">  </span><span class="cm">/* ... */</span>
<span class="p">});</span>
</pre></div>

<p>The relevant part is the <code>backgroundColor</code>. The
<code>nativeTheme.shouldUseDarkColors</code> API is the way to check whether the OS is in
dark more inside the main process (as opposed to the render process where we can
use media queries).</p>

<h3>Settings</h3>

<p>The app's theme is one of its many settings. The way settings work in general is
also an interesting topic. I've been using <code>electron-store</code> to store the app
settings. This package abstracts a native store which supports typed schemas and
version migrations of settings:
<a href="https://github.com/sindresorhus/electron-store">https://github.com/sindresorhus/electron-store</a>.</p>

<p>The store works on the main process, which means I had to implement IPC to
get/set settings on the render process. This type of IPC is common for Electron
apps and follows the same pattern as I describe in the <a href="https://vladris.com/blog/2025/05/08/devlog-3-commanding.html">Commanding
post</a>. As a quick
recap, the render process talks to the main process via
<code>window.electronAPI.invoke</code> and the main process receives and handles these
events. Here's how the render process asks for a setting item:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">getStoreItem</span><span class="o">&lt;</span><span class="nx">K</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">keyof</span><span class="w"> </span><span class="nx">StoreType</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">K</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">StoreType</span><span class="p">[</span><span class="nx">K</span><span class="p">]</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">electronAPI</span><span class="p">.</span><span class="nx">invoke</span><span class="p">(</span><span class="nx">GET_STORE_ITEM</span><span class="p">,</span><span class="w"> </span><span class="nx">key</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Here <code>StoreType</code> is the strongly typed store schema and <code>GET_STORE_ITEM</code> is just
a string to identify the event type.</p>

<p>On the main process side, this is handled via:</p>
<div class="highlight"><pre><span/><span class="nx">ipcMain</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="nx">GET_STORE_ITEM</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">keyof</span><span class="w"> </span><span class="nx">StoreType</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="p">});</span>
</pre></div>

<p>With IPC taken care of, I implemented a React provider that wraps the IPC code
and exposes the settings via a <code>SettingsContext</code>. Theming becomes super-easy
with this. For example, inside the React component implementing the main view:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">EditorContent</span><span class="o">:</span><span class="w"> </span><span class="kt">React.FC</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">theme</span><span class="p">,</span><span class="w"> </span><span class="nx">font</span><span class="p">,</span><span class="w"> </span><span class="nx">fontSize</span><span class="p">,</span><span class="w"> </span><span class="nx">autoIndent</span><span class="p">,</span><span class="w"> </span><span class="nx">lineHeight</span><span class="p">,</span><span class="w"> </span><span class="nx">paragraphSpacing</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>
<span class="w">        </span><span class="nx">useSettings</span><span class="p">();</span>

<span class="w">    </span><span class="cm">/* ... */</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">(</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">className</span><span class="o">=</span><span class="p">{</span><span class="sb">`app-container </span><span class="si">${</span><span class="nx">theme</span><span class="si">}</span><span class="sb">`</span><span class="p">}</span><span class="o">&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">TitleBar</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">SideBar</span><span class="w"> </span><span class="o">/&gt;</span>

<span class="w">            </span><span class="o">&lt;</span><span class="nx">Editor</span><span class="w"> </span><span class="p">{...</span><span class="nx">editorProps</span><span class="p">}</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">StatusBar</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="err">/div&gt;);</span>
<span class="w">    </span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Note any component can easily get the settings from the provider and, in the
case of theming, we simply use it as a <code>className</code> prop inside the JSX.</p>

<p>The provider also allows consumers to update the various settings. For example,
for theming, it exposes an <code>updateTheme()</code> API that allows components to update
the setting.</p>

<h3>Multiple windows</h3>

<p>When working with theming though, a reasonable expectation would be to have the
theme change across the all open app windows. So as soon as I select the <code>Latte</code>
theme from the theme picker in the Settings window, the main window should
change colors.</p>

<p>The existing IPC mechanism I described so far isn't sufficient for that: the
render process can get and set settings, but a key missing piece is that, as
soon as a setting changes, the main process needs to broadcast this to all
window instances.</p>

<p>Previously I shared the implementation of the main process's <code>GET_ITEM</code> handler:</p>
<div class="highlight"><pre><span/><span class="nx">ipcMain</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span><span class="nx">GET_STORE_ITEM</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">keyof</span><span class="w"> </span><span class="nx">StoreType</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="p">});</span>
</pre></div>

<p>The <code>SET_ITEM</code> handler does a bit more work:</p>
<div class="highlight"><pre><span/><span class="nx">ipcMain</span><span class="p">.</span><span class="nx">handle</span><span class="p">(</span>
<span class="w">    </span><span class="nx">SET_STORE_ITEM</span><span class="p">,</span>
<span class="w">    </span><span class="o">&lt;</span><span class="nx">K</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">keyof</span><span class="w"> </span><span class="nx">StoreType</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">_</span><span class="o">:</span><span class="w"> </span><span class="kt">unknown</span><span class="p">,</span>
<span class="w">    </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">K</span><span class="p">,</span>
<span class="w">    </span><span class="nx">value?</span><span class="o">:</span><span class="w"> </span><span class="kt">StoreType</span><span class="p">[</span><span class="nx">K</span><span class="p">]</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">store</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="p">);</span>

<span class="w">    </span><span class="nx">BrowserWindow</span><span class="p">.</span><span class="nx">getAllWindows</span><span class="p">().</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">win</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">win</span><span class="p">.</span><span class="nx">webContents</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">SETTING_CHANGED</span><span class="p">,</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">key</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="p">});</span>
<span class="w">    </span><span class="p">});</span>
<span class="p">}</span>
</pre></div>

<p>The function takes a key of type <code>K</code> which needs to be part of the store schema
and an optional value of that type. This is the standard to call the <code>store</code>
API, which happens on the first lie (<code>store.set(key, value);</code>). Then, once the
value is stored, I use the Electron API to sent a <code>SETTING_CHANGED</code> event to all
windows and pass them the <code>key</code> that changed and the new <code>value</code>.</p>

<p>On the render process side, we listen to the event on the window, and update the
corresponding setting in the provider:</p>
<div class="highlight"><pre><span/><span class="nb">window</span><span class="p">.</span><span class="nx">electronAPI</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="nx">SETTING_CHANGED</span><span class="p">,</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">key</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">data</span><span class="p">;</span>
<span class="w">    </span><span class="cm">/* Update setting */</span>
<span class="p">}</span>
</pre></div>

<p>This way, changes reflect instantly across the app.</p>

<h3>Additional considerations</h3>

<p>A benefit of using CSS variables for themes is that it's super easy to implement
the different theme cards in the Settings window. A theme card is a React
component to which we apply the theme we want it to display, and since we have a
CSS class for each theme, we can put together the gallery with very little code:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">ThemeCard</span><span class="o">:</span><span class="w"> </span><span class="kt">React.FC</span><span class="o">&lt;</span><span class="nx">ThemeCardProps</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">({</span><span class="w"> </span><span class="nx">title</span><span class="p">,</span><span class="w"> </span><span class="nx">className</span><span class="p">,</span><span class="w"> </span><span class="nx">current</span><span class="p">,</span><span class="w"> </span><span class="nx">onClick</span><span class="w"> </span><span class="p">})</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">(</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">className</span><span class="o">=</span><span class="p">{</span><span class="sb">`theme-card </span><span class="si">${</span><span class="nx">className</span><span class="si">}</span><span class="sb">`</span><span class="p">}</span><span class="w"> </span><span class="nx">onClick</span><span class="o">=</span><span class="p">{</span><span class="nx">onClick</span><span class="p">}</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">current</span><span class="o">=</span><span class="p">{</span><span class="nx">current</span><span class="p">}</span><span class="o">&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">className</span><span class="o">=</span><span class="s2">"theme-card-content"</span><span class="o">&gt;</span>
<span class="w">                </span><span class="o">&lt;</span><span class="nx">h2</span><span class="w"> </span><span class="nx">className</span><span class="o">=</span><span class="s2">"theme-card-title"</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">title</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/h2&gt;</span>
<span class="w">                </span><span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="s2">"The universe is made of stories, not atoms."</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">                </span><span class="p">{</span><span class="cm">/* Rest of card content */</span><span class="p">}</span>
<span class="w">            </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">    </span><span class="p">);</span>
<span class="p">};</span>
</pre></div>

<p>The gallery becomes just a sequence of <code>ThemeCard</code>s with different props.</p>

<h2>On footguns</h2>

<p>This brings me to the funny part of the journey. I started building Flow as a
macOS app but based it on Electron on the idea that it will be easy to bring it
to Windows. As I started looking into a Windows version, I hit a strange snag I
didn't consider when I was focused on macOS: the menu.</p>

<p>On macOS, the menu bar shows at the top of the screen. I described in the
<a href="https://vladris.com/blog/2025/05/08/devlog-3-commanding.html">Commanding post</a>
how the commands end up in a registry which I serialize and send to the main
process to set up the native menu.</p>

<p>On Windows on the other hand, the menu bar appears on the window itself. And, of
course, the native menu is not themeable. Worse, because I'm theming the whole
app, I use a custom title bar since it would otherwise get the default system
colors. The menu bar is part of the browser window on Windows, so there is no
way to put anything before it.</p>

<p>The only reasonable conclusion, which I guess all Electron apps that support
theming do, is that I need a custom menu bar implementation for Windows. That
is, a full React menu system that binds to the commanding infrastructure.</p>

<p>The reason I find this extremely funny is that I picked Electron to write once
and run everywhere, and it seems I'll end up with a ton of platform-specific
code: on macOS, set up the native menu on the main process; on Windows, set up a
custom menu on the render process.</p>

<h2>Summary</h2>

<p>In this post I talked about how I implemented theming in Flow, and settings more
generally:</p>

<ul>
<li>Themes are implemented as CSS classes overriding CSS variables.</li>
<li>Some boot considerations: being aware of dark mode before user picked a
specific theme.</li>
<li>I use <code>electron-store</code> to store the settings.</li>
<li>A <code>SettingsProvider</code> on the render process handles IPC.</li>
<li>The main process broadcasts all setting changes to all active windows so any
change is reflected instantly across the whole app.</li>
<li>The interesting issue I ran into where on Mac the menu is handled by the main</li>
<li>process but on Windows, as long as I want custom theming throughout the app,
the menu must be custom-built thus run in the render process.</li>
</ul>

<p><em>This post was written with Flow. Try it out <a href="https://saturn9.studio/flow/">here</a>.</em></p>
]]></description>
      <pubDate>Sun, 03 Aug 2025 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/06/08/digital-horology.html</link>
      <guid>https://vladris.com/blog/2025/06/08/digital-horology.html</guid>
      <title><![CDATA[Digital Horology]]></title>
      <description><![CDATA[<h1>Digital Horology</h1>

<p>I started getting ads for <a href="https://www.klydoclock.com/">Klydoclock</a> on
Instagram. The product looks really neat:</p>

<div style="width: 90%; position: relative; aspect-ratio: 16 / 9; margin: 0 auto;">
<iframe style="position: absolute; top: 0; left: 0; width: 100%; height: 100%" src="https://www.youtube-nocookie.com/embed/gmyS-SMnW0U?si=CBJds1yeQxd-s9nO" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
</div>

<p>I love the idea of a digital pendulum clock. I figured it would make for a cool
DIY project: implement the clock display, then run it on a cheap tablet I can
stick in a box. Of course, the Klydo folks build a cool product, working with
multiple artists for the various clock faces, and, from what I can tell based on
the videos, it's a polished product. I'm not trying to dunk on their hard work.
I was simply intrigued by how one would go about implementing a pendulum clock.</p>

<p>I spent a couple of days playing with how I would implement something like this.
Here's what I have so far:</p>

<div class="container">
    <div class="circle top-circle">
        <div class="clock">
            <div class="hand hour-hand"/>
            <div class="hand minute-hand"/>
            <div class="pin"/>
        </div>
    </div>
    <div class="circle bottom-circle">
        <div class="pendulum">
            <div class="pendulum-line"/>
            <div class="pendulum-circle"/>
        </div>
    </div>
</div>

<p>This was built with a little bit of HTML, some CSS, and a dash of JavaScript. I
have a love-hate relationship with CSS. From centering a div, to debugging
obscure layout issues, I always think of this GIF:</p>

<p><img src="./css.gif" alt="CSS"/></p>

<p>That said, it's incredible how much one can achieve with CSS. In this blog post,
I'll go over the clock implementation. I'll show some inline renderings of the
clock, tweaked to be embedded inside this post. The original, unmodified source
code is at <a href="https://github.com/vladris/vladris.github.io/tree/master/clock">https://github.com/vladris/vladris.github.io/tree/master/clock</a>, and
live at <a href="https://github.com/vladris/clock/">https://github.com/vladris/clock/</a>. For example, a notable difference
in the original implementation is sizes are specified in <code>vh</code> units, as I built
it for full-screen rendering, but for the clocks embedded in this post the CSS
uses <code>px</code> units. The code snippets are taken from the original implementation,
so <u>view source</u> won't be as helpful. Now let's build a clock!</p>

<h2>Pendulum</h2>

<p>The most notable feature of the clock is the pendulum. I implemented this as 4
divs:</p>
<div class="highlight"><pre><span/><span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"bottom-circle"</span> <span class="na">class</span><span class="o">=</span><span class="s">"circle"</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"pendulum"</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"pendulum-line"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"pendulum-circle"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</pre></div>

<p>The <code>circle</code> class is just to make the div render as a circle, which we can do
with CSS like this:</p>
<div class="highlight"><pre><span/><span class="p">.</span><span class="nc">circle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">border-radius</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The <code>bottom-circle</code> further configures this:</p>
<div class="highlight"><pre><span/><span class="p">#</span><span class="nn">bottom-circle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">25</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">25</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">relative</span><span class="p">;</span>
<span class="w">    </span><span class="k">overflow</span><span class="p">:</span><span class="w"> </span><span class="kc">hidden</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>We want a set height and width for it, and we want anything that ends up outside
of the circle to be hidden.</p>

<p>Now here comes the fun part: the pendulum itself. The pendulum consists of a line
and a circle, wrapped inside a container div:</p>
<div class="highlight"><pre><span/><span class="p">.</span><span class="nc">pendulum</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="w">    </span><span class="k">top</span><span class="p">:</span><span class="w"> </span><span class="mi">-21</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mf">44.5</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">translateX</span><span class="p">(</span><span class="mi">-50</span><span class="kt">%</span><span class="p">);</span>
<span class="p">}</span>

<span class="p">.</span><span class="nc">pendulum-circle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">22</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">22</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">border-radius</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">box-shadow</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">10</span><span class="kt">px</span><span class="w"> </span><span class="mi">20</span><span class="kt">px</span><span class="w"> </span><span class="nb">rgba</span><span class="p">(</span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">);</span>
<span class="w">    </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="w">    </span><span class="k">bottom</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">translateX</span><span class="p">(</span><span class="mi">-50</span><span class="kt">%</span><span class="p">);</span>
<span class="p">}</span>

<span class="p">.</span><span class="nc">pendulum-line</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">2</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">35</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">top</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">translateX</span><span class="p">(</span><span class="mi">-50</span><span class="kt">%</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>The divs have <code>left: 50%</code> and <code>transform: translateX(-50%)</code>. This centers them
inside their container. The <code>box-shadow</code> adds a nice shadow effect. Here's what
we have so far:</p>

<div class="container">
    <div class="circle top-circle" style="background: black">
    </div>
    <div class="circle bottom-circle">
        <div class="pendulum" style="animation: none">
            <div class="pendulum-line"/>
            <div class="pendulum-circle"/>
        </div>
    </div>
</div>

<p>And here comes the swing animation:</p>
<div class="highlight"><pre><span/><span class="p">.</span><span class="nc">pendulum</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="err">...</span>

<span class="w">    </span><span class="k">animation</span><span class="p">:</span><span class="w"> </span><span class="n">swing</span><span class="w"> </span><span class="mi">2</span><span class="kt">s</span><span class="w"> </span><span class="kc">infinite</span><span class="w"> </span><span class="kc">ease-in-out</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">translateX</span><span class="p">(</span><span class="mi">-50</span><span class="kt">%</span><span class="p">);</span>
<span class="p">}</span>

<span class="p">@</span><span class="k">keyframes</span><span class="w"> </span><span class="nt">swing</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nt">0</span><span class="o">%</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">rotate</span><span class="p">(</span><span class="mi">-5</span><span class="kt">deg</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="nt">50</span><span class="o">%</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">rotate</span><span class="p">(</span><span class="mi">5</span><span class="kt">deg</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="nt">100</span><span class="o">%</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">rotate</span><span class="p">(</span><span class="mi">-5</span><span class="kt">deg</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This applies a <code>swing</code> animation to the pendulum, which rotates the whole
thing by 5 degrees on each side:</p>

<div class="container">
    <div class="circle top-circle" style="background: black">
    </div>
    <div class="circle bottom-circle">
        <div class="pendulum">
            <div class="pendulum-line"/>
            <div class="pendulum-circle"/>
        </div>
    </div>
</div>

<p>The <q>trick</q> to it is the pendulum top is high outside the circle. The animation
is anchored there (<code>transform-origin: top</code>) and the motion itself is only 5
degrees each way.</p>

<h2>Clock face</h2>

<p>The top part of the clock looks like this:</p>
<div class="highlight"><pre><span/><span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"top-circle"</span> <span class="na">class</span><span class="o">=</span><span class="s">"circle"</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"clock"</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"hand"</span> <span class="na">id</span><span class="o">=</span><span class="s">"hour-hand"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"hand"</span> <span class="na">id</span><span class="o">=</span><span class="s">"minute-hand"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"pin"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</pre></div>

<p>The classic typeface is called <u>Breguet</u>, named after the luxury watch company
that introduced it. Luckily, I found a free SVG with a Breguet dial:</p>

<p><img src="https://vladris.com/blog/2025/06/08/https://vladris.com/clock/breguet/breguet.svg" alt="Breguet"/></p>

<p>We can use this as the background of the top circle:</p>
<div class="highlight"><pre><span/><span class="p">#</span><span class="nn">top-circle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">background-size</span><span class="p">:</span><span class="w"> </span><span class="kc">cover</span><span class="p">;</span>
<span class="w">    </span><span class="k">background-image</span><span class="p">:</span><span class="w"> </span><span class="nb">url</span><span class="p">(</span><span class="s2">"breguet.svg"</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>The nice thing about SVGs is they scale very smoothly.</p>

<div class="container">
    <div class="circle top-circle">
    </div>
    <div class="circle bottom-circle">
        <div class="pendulum">
            <div class="pendulum-line"/>
            <div class="pendulum-circle"/>
        </div>
    </div>
</div>

<p>We need hour and minute hands, and also a <q>pin</q> in the middle. We already
saw these in the clock top HTML:</p>
<div class="highlight"><pre><span/><span class="p">&lt;</span><span class="nt">div</span> <span class="na">id</span><span class="o">=</span><span class="s">"top-circle"</span> <span class="na">class</span><span class="o">=</span><span class="s">"circle"</span><span class="p">&gt;</span>
    <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"clock"</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"hand"</span> <span class="na">id</span><span class="o">=</span><span class="s">"hour-hand"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"hand"</span> <span class="na">id</span><span class="o">=</span><span class="s">"minute-hand"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">"pin"</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
    <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</pre></div>

<p>The styling for the clock face:</p>
<div class="highlight"><pre><span/><span class="p">#</span><span class="nn">top-circle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">margin-bottom</span><span class="p">:</span><span class="w"> </span><span class="mi">5</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">relative</span><span class="p">;</span>
<span class="w">    </span><span class="k">background-size</span><span class="p">:</span><span class="w"> </span><span class="kc">cover</span><span class="p">;</span>
<span class="w">    </span><span class="k">background-image</span><span class="p">:</span><span class="w"> </span><span class="nb">url</span><span class="p">(</span><span class="s2">"breguet.svg"</span><span class="p">);</span>
<span class="p">}</span>

<span class="p">.</span><span class="nc">clock</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="w">    </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">border-radius</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">top</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">translate</span><span class="p">(</span><span class="mi">-50</span><span class="kt">%</span><span class="p">,</span><span class="w"> </span><span class="mi">-50</span><span class="kt">%</span><span class="p">);</span>
<span class="p">}</span>

<span class="p">.</span><span class="nc">pin</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mf">0.5</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mf">0.5</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">border-radius</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="w">    </span><span class="k">top</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">translate</span><span class="p">(</span><span class="mi">-50</span><span class="kt">%</span><span class="p">,</span><span class="w"> </span><span class="mi">-50</span><span class="kt">%</span><span class="p">);</span>
<span class="p">}</span>

<span class="p">.</span><span class="nc">hand</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">position</span><span class="p">:</span><span class="w"> </span><span class="kc">absolute</span><span class="p">;</span>
<span class="w">    </span><span class="k">box-shadow</span><span class="p">:</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">10</span><span class="kt">px</span><span class="w"> </span><span class="nb">rgba</span><span class="p">(</span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">);</span>
<span class="w">    </span><span class="k">stroke-width</span><span class="p">:</span><span class="w"> </span><span class="mi">100</span><span class="p">;</span>
<span class="w">    </span><span class="k">top</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">left</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
<span class="w">    </span><span class="k">border-radius</span><span class="p">:</span><span class="w"> </span><span class="mi">1</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">translate</span><span class="p">(</span><span class="mi">-50</span><span class="kt">%</span><span class="p">,</span><span class="w"> </span><span class="mi">-15</span><span class="kt">%</span><span class="p">);</span>
<span class="p">}</span>

<span class="p">#</span><span class="nn">hour-hand</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">17</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mf">1.8</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform-origin</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="w"> </span><span class="mi">15</span><span class="kt">%</span><span class="p">;</span>
<span class="p">}</span>

<span class="p">#</span><span class="nn">minute-hand</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">height</span><span class="p">:</span><span class="w"> </span><span class="mi">22</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">width</span><span class="p">:</span><span class="w"> </span><span class="mf">1.2</span><span class="kt">vh</span><span class="p">;</span>
<span class="w">    </span><span class="k">transform-origin</span><span class="p">:</span><span class="w"> </span><span class="mi">50</span><span class="kt">%</span><span class="w"> </span><span class="mi">15</span><span class="kt">%</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This looks like a lot but it really isn't: we center the clock with
<code>left: 50%; top: 50%; transform: translate(-50%, -50%)</code>. We do the same
with the pin, this is just a small circle at the very center of the clock.</p>

<p>The hour and minute hands are similarly centered, with a slightly different
<code>translate</code>: <code>translate(-50%, -15%)</code> - we want them to look like the pin
goes through them at 15% of their length. We also add shadows to the hands.</p>

<div class="container">
    <div class="circle top-circle">
        <div class="clock">
            <div class="hand" style="height: 100px; width: 10px; transform-origin: 50% 15%"/>
            <div class="hand" style="height: 120px; width: 6px; transform-origin: 50% 15%"/>
            <div class="pin"/>
        </div>
    </div>
    <div class="circle bottom-circle">
        <div class="pendulum">
            <div class="pendulum-line"/>
            <div class="pendulum-circle"/>
        </div>
    </div>
</div>

<p>Almost done! The only thing we need to do is show the time. This is where the
bit of JavaScript comes in:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">updateClock</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">now</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Date</span><span class="p">();</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">minutes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">now</span><span class="p">.</span><span class="nx">getMinutes</span><span class="p">();</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">hours</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">now</span><span class="p">.</span><span class="nx">getHours</span><span class="p">();</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">minuteDegree</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">minutes</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">60</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">360</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">seconds</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">60</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">6</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">180</span><span class="p">;</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">hourDegree</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">hours</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">12</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">360</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">minutes</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">60</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">30</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">180</span><span class="p">;</span>

<span class="w">    </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span>
<span class="w">        </span><span class="s2">"minute-hand"</span>
<span class="w">    </span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">transform</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sb">`translate(-50%, -15%) rotate(</span><span class="si">${</span><span class="nx">minuteDegree</span><span class="si">}</span><span class="sb">deg)`</span><span class="p">;</span>
<span class="w">    </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span>
<span class="w">        </span><span class="s2">"hour-hand"</span>
<span class="w">    </span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">transform</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sb">`translate(-50%, -15%) rotate(</span><span class="si">${</span><span class="nx">hourDegree</span><span class="si">}</span><span class="sb">deg)`</span><span class="p">;</span>
<span class="p">}</span>

<span class="nx">setInterval</span><span class="p">(</span><span class="nx">updateClock</span><span class="p">,</span><span class="w"> </span><span class="mf">1000</span><span class="p">);</span>
<span class="nx">updateClock</span><span class="p">();</span>
</pre></div>

<p>We implement an <code>updateClock()</code> function that gets the current time and rotates
the hands. We compute how many degrees we want the minute hand and the hour hand
to be rotated by:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">minuteDegree</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">minutes</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">60</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">360</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">seconds</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">60</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">6</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">180</span><span class="p">;</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">hourDegree</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">hours</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">12</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">360</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="nx">minutes</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">60</span><span class="p">)</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">30</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">180</span><span class="p">;</span>
</pre></div>

<p>Note the minute hand also takes into account the seconds while the hour hand
takes into account the minutes, to ensure smooth movement.</p>

<p>We then get the <code>minute-hand</code> and <code>hour-hand</code> elements and update their
<code>transform</code> to include a <code>rotate</code> by the determined number of degrees.</p>

<p>We use <code>setInterval()</code> to run <code>updateClock</code> every second. And that's it!</p>

<div class="container">
    <div class="circle top-circle">
        <div class="clock">
            <div class="hand hour-hand"/>
            <div class="hand minute-hand"/>
            <div class="pin"/>
        </div>
    </div>
    <div class="circle bottom-circle">
        <div class="pendulum">
            <div class="pendulum-line"/>
            <div class="pendulum-circle"/>
        </div>
    </div>
</div>

<h2>Skins</h2>

<p>Since all the styling is done with CSS, it's very easy to provide multiple
skins for it, much like Klydo does. Here's a Mickey Mouse version:</p>

<div class="container">
    <div class="circle top-circle" style="background-image: url(https://vladris.com/clock/mickey/mickey.gif); width: 240px; height: 240px; margin: 20px 0 30px 0">
        <div class="clock">
            <div class="hand hour-hand" style="background-color: #f4c81d"/>
            <div class="hand minute-hand" style="background-color: #f4c81d"/>
            <div class="pin"/>
        </div>
    </div>
    <div class="circle bottom-circle" style="background-color: #b49a7d">
        <div class="pendulum">
            <div class="pendulum-line" style="background-color: #040204"/>
            <div class="pendulum-circle" style="background-color: #c13941"/>
        </div>
    </div>
</div>

<p>In fact, in my original implementation I have several clock faces, each coming
with a set of color customizations and a background image for the clock. The
following JavaScript looks for a <code>style</code> query parameter and loads the specified
CSS file:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">loadCSSFromQueryParam</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">urlParams</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">URLSearchParams</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">search</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">style</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">urlParams</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="s2">"style"</span><span class="p">)</span><span class="w"> </span><span class="o">??</span><span class="w"> </span><span class="s2">"breguet"</span><span class="p">;</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">styleParam</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="sb">`</span><span class="si">${</span><span class="nx">style</span><span class="si">}</span><span class="sb">/style.css`</span><span class="p">;</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">styleParam</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">link</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s2">"link"</span><span class="p">);</span>
<span class="w">        </span><span class="nx">link</span><span class="p">.</span><span class="nx">rel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"stylesheet"</span><span class="p">;</span>
<span class="w">        </span><span class="nx">link</span><span class="p">.</span><span class="nx">href</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">styleParam</span><span class="p">;</span>
<span class="w">        </span><span class="nb">document</span><span class="p">.</span><span class="nx">head</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">link</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="nx">loadCSSFromQueryParam</span><span class="p">();</span>
</pre></div>

<p>The default is <code>breguet</code>, loading the Breguet dial, but using <code>style=mickey</code> in
<a href="https://vladris.com/clock/?style=mickey">https://vladris.com/clock/?style=mickey</a> loads the Mickey Mouse face.</p>

<h2>Conclusions</h2>

<p>CSS is still very cumbersome, but it's impressive how easy it is to achieve
quite complex effects with it. Adding a subtle shadow can be done with a
<code>box-shadow</code> one-liner. The pendulum animation is a simple <code>rotate</code>
transform with 3 keyframes:</p>
<div class="highlight"><pre><span/><span class="p">@</span><span class="k">keyframes</span><span class="w"> </span><span class="nt">swing</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nt">0</span><span class="o">%</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">rotate</span><span class="p">(</span><span class="mi">-5</span><span class="kt">deg</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="nt">50</span><span class="o">%</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">rotate</span><span class="p">(</span><span class="mi">5</span><span class="kt">deg</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="nt">100</span><span class="o">%</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">transform</span><span class="p">:</span><span class="w"> </span><span class="nb">rotate</span><span class="p">(</span><span class="mi">-5</span><span class="kt">deg</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Similarly, having the hands point to the right time is just another <code>rotate</code>.
Quite nice!</p>

<p>The full implementation we went over is <a href="https://github.com/vladris/vladris.github.io/blob/master/clock/index.html">here</a>.</p>

<style>
.container {
    margin: auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    height: 480px;
    background-color: black;
    border-radius: 20px;
    width: 300px;
}
.circle {
    border-radius: 50%;
}
.top-circle {
    width: 280px;
    height: 280px;
    margin-bottom: 10px;
    position: relative;
    background-size: cover;
    background-image: url(https://vladris.com/clock/breguet/breguet.svg);
}
.bottom-circle {
    width: 140px;
    height: 140px;
    position: relative;
    overflow: hidden;
    background-color: #f7ebd3;
}
.clock {
    position: absolute;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
}
.pin {
    width: 3px;
    height: 3px;
    border-radius: 50%;
    position: absolute;
    top: 50%;
    left: 50%;
    background-color: #905923;
    transform: translate(-50%, -50%);
}
.hand {
    position: absolute;
    box-shadow: 0 0 10px rgba(0 0 0 / 50%);
    stroke-width: 100;
    top: 50%;
    left: 50%;
    border-radius: 6px;
    background-color: #cd7f23;
    transform: translate(-50%, -15%);
}
.hour-hand {
    height: 100px;
    width: 10px;
    transform-origin: 50% 15%;
}
.minute-hand {
    height: 120px;
    width: 6px;
    transform-origin: 50% 15%;
}
.pendulum {
    position: absolute;
    top: -120px;
    left: 50%;
    height: 250px;
    transform-origin: top;
    animation: swing 2s infinite ease-in-out;
    transform: translateX(-50%);
}
.pendulum-circle {
    width: 120px;
    height: 120px;
    border-radius: 50%;
    box-shadow: 0 10px 20px rgba(0 0 0 / 50%);
    position: absolute;
    bottom: 0;
    left: 50%;
    background-color: #cd7f32;
    transform: translateX(-50%);
}
.pendulum-line {
    width: 12px;
    height: 240px;
    top: 0;
    left: 50%;
    position: absolute;
    background-color: #905923;
    transform: translateX(-50%);
}
@keyframes swing {
    0% { transform: rotate(-5deg); }
    50% { transform: rotate(5deg); }
    100% { transform: rotate(-5deg); }
}
</style>

<script>
    function updateClock() {
        const now = new Date();
        const seconds = now.getSeconds();
        const minutes = now.getMinutes();
        const hours = now.getHours();

        const minuteDegree = ((minutes / 60) * 360) + ((seconds / 60) * 6) + 180;
        const hourDegree = ((hours / 12) * 360) + ((minutes / 60) * 30) + 180;

        for (const elem of document.getElementsByClassName("minute-hand")) {
            elem.style.transform = `translate(-50%, -15%) rotate(${minuteDegree}deg)`;
        }

        for (const elem of document.getElementsByClassName("hour-hand")) {
            elem.style.transform = `translate(-50%, -15%) rotate(${hourDegree}deg)`;
        }
    }

    setInterval(updateClock, 1000);
    updateClock();
</script>
]]></description>
      <pubDate>Sun, 08 Jun 2025 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/05/08/devlog-3-commanding.html</link>
      <guid>https://vladris.com/blog/2025/05/08/devlog-3-commanding.html</guid>
      <title><![CDATA[DevLog 3: Commanding]]></title>
      <description><![CDATA[<h1>DevLog 3: Commanding</h1>

<p>This article is going to be the part 2 of the <em>formatting and commanding</em> I
built for <a href="https://saturn9.studio/flow/">Flow</a>. In the <a href="https://vladris.com/blog/2025/04/04/devlog-2-formatting.html">previous
post</a> I covered
formatting and the various corner cases we need to keep in mind when
implementing something as simple as <em>toggle bold on the current selection</em>. Last
post dealt with what we need to do to update the document when such a command
comes in. Now that thatâs taken care of, letâs see how we can expose of these
formatting commands (and more) to an app hosting our editor.</p>

<p>Letâs go over what a well-behaved editor needs to do. Commands like âtoggle
boldâ can be shown to the user in multiple places: app menu bar, toolbar,
context menu etc. We need to make sure invoking a command for any of these
places does the same thing. More so, a command like âtoggle boldâ is stateful.
If the selected text is already bold, we should show a checkmark next to the
Bold menu item and show the Bold button in the toolbar depressed. If the editor
is, for whatever reason, in read-only mode, the command should be disabled and
the corresponding UI element should be grayed out.</p>

<p>Of course, we need to be consistent - if a command is disabled, it should be
disabled everywhere, not show up as enabled in the menu bar but disabled in the
toolbar or vice-versa. Also, invoking it from anywhere should yield the exact
same results.</p>

<p>Even before diving into the technical details, given the requirements itâs quite
obvious we need some form of object representation for a command, including some
state, like whether the command is active (e.g. current selection is Bold) and
enabled, and an action we can invoke when we want to apply the command.</p>

<p>This will be the focus of this post, with some extra complications: while
formatting is neatly contained within the editor, commands allow the hosting app
to change editor state. More so, I built Flow as an Electron app. An Electron
app runs a <em>main process</em>, running the Node code and communicating with the OS,
and a <em>render process</em>, running a browser. The editor is, of course, hosted on
the render process, but the menu bar and context menu are handled by the main
process as they are relying on OS-native features. The commanding infrastructure
needs to keep command state in sync across processes!</p>

<p>Another complication is that we might have commands that arenât related to
formatting. In fact, they might not involve the editor at all. A few examples:
in Flow, you can switch from Focus Mode to Edit Mode to Read Mode to Source
Mode. These reconfigure the view but donât mutate the document. We also have
commands like <em>show the settings window</em> which has nothing to do with the
editor. And while these could, of course, be implemented through a completely
different architecture, it makes sense to weave them into the general commanding
infrastructure. </p>

<p>Hereâs what I did for Flow:</p>

<h2>Commands</h2>

<p>The basic building block is the <code>Command</code>:</p>
<div class="highlight"><pre><span/><span class="kd">interface</span><span class="w"> </span><span class="nx">Command</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">label</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">accelerator?</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">enabled</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kt">boolean</span><span class="p">;</span>
<span class="w">    </span><span class="nx">active</span><span class="o">?:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kt">boolean</span><span class="p">;</span>
<span class="w">    </span><span class="nx">execute</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">...args</span><span class="o">:</span><span class="w"> </span><span class="kt">any</span><span class="p">[])</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">unknown</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>In Flow, a <code>Command</code> has:</p>

<ul>
<li>A unique id.</li>
<li>A label (whatâs going to be shown in the menu for example).</li>
<li>An optional keyboard shortcut (<code>accelerator</code>).</li>
<li>A function that should tell us whether the command is enabled or not.</li>
<li>An optional function that should tell us whether we should show a checkmark
next to its menu entry (or show its button depressed) - note this is optional
as not all commands are âtoggleâ commands.</li>
<li>A way to invoke the command passing some arguments to it.</li>
</ul>

<p>This is pretty straight-forward, but things get a bit more complicated: since we
need to show command state across the main and render processes, we need a way
to pass command data between them. Functions are not serializable, so we also
need a <code>CommandData</code> way to pass information:</p>
<div class="highlight"><pre><span/><span class="kd">interface</span><span class="w"> </span><span class="nx">CommandData</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">label</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">accelerator?</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">enabled</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="p">;</span>
<span class="w">    </span><span class="nx">active?</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">?:</span><span class="w"> </span><span class="s2">"normal"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"checkbox"</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Thinks of <code>CommandData</code> as an instance in time of a <code>Command</code>. It captures a
commandâs state and can pass it from the render process where the editor lives
to the app process. You might have noticed an extra property: <code>type</code> tells the
UI whether this command should show up as a ânormalâ command, or as a command
that can have a checkmark next to it. A ânormalâ command without a checkbox is
something like <em>insert a horizontal rule</em>. A command with a checkbox is
something like <em>toggle bold</em>.</p>

<p>We also have a straight-forward way of serializing a <code>Command</code> into its
<code>CommandData</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">commandDataFromCommand</span><span class="p">(</span><span class="nx">command</span><span class="o">:</span><span class="w"> </span><span class="kt">Command</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">CommandData</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">command.id</span><span class="p">,</span>
<span class="w">        </span><span class="nx">label</span><span class="o">:</span><span class="w"> </span><span class="kt">command.label</span><span class="p">,</span>
<span class="w">        </span><span class="nx">accelerator</span><span class="o">:</span><span class="w"> </span><span class="kt">command.accelerator</span><span class="p">,</span>
<span class="w">        </span><span class="nx">enabled</span><span class="o">:</span><span class="w"> </span><span class="kt">command.enabled</span><span class="p">(),</span>
<span class="w">        </span><span class="nx">active</span><span class="o">:</span><span class="w"> </span><span class="kt">command.active</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">command</span><span class="p">.</span><span class="nx">active</span><span class="p">()</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="kc">undefined</span><span class="p">,</span>
<span class="w">        </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="nx">command</span><span class="p">.</span><span class="nx">active</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"checkbox"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"normal"</span><span class="p">,</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>This way, we can pass the current command state from the render process to the
main process whenever the editor state changes in any way.</p>

<h2>The command registry</h2>

<p>Of course, we will have many commands so need a way to keep them together. Enter
the <code>CommandRegistry</code>:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">CommandRegistry</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">commands</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Map</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">Command</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">listeners</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Set</span><span class="o">&lt;</span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="nx">register</span><span class="p">(</span><span class="nx">command</span><span class="o">:</span><span class="w"> </span><span class="kt">Command</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">commands</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">command</span><span class="p">.</span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">command</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">getCommand</span><span class="p">(</span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Command</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">commands</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">id</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">getAllCommands</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Command</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nb">Array</span><span class="p">.</span><span class="kr">from</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">commands</span><span class="p">.</span><span class="nx">values</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">getCommandData</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">SerializedCommandRegistry</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">commands</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Map</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">CommandData</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">commands</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">command</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">commands</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">command</span><span class="p">.</span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">commandDataFromCommand</span><span class="p">(</span><span class="nx">command</span><span class="p">));</span>
<span class="w">        </span><span class="p">});</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">commands</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">onUpdate</span><span class="p">(</span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="nx">listener</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">offUpdate</span><span class="p">(</span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="ow">delete</span><span class="p">(</span><span class="nx">listener</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">emitUpdate</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">listeners</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">listener</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">listener</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>The <code>CommandRegistry</code> wraps a set of commands and allows consumers to subscribe
to notifications for when the state changes.</p>

<p>The <code>register()</code>, <code>getCommand()</code>,  <code>getAllCommands()</code> are trivial.
<code>getCommandData()</code> serializes the whole registry. Itâs return type,
<code>SerializedCommandRegistry</code>, is:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">SerializedCommandRegistry</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Map</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">CommandData</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>The remaining functions, <code>onUpdate()</code>, <code>offUpdate()</code>, and <code>emitUpdate()</code> handle
notifications. Subscribers can start listening to command state change updates
via <code>onUpdate()</code> and unsubscribe via <code>offUpdate()</code>. Finally, <code>emitUpdate()</code> is
called by whoever changes command state such that subscribers are notified of
the change.</p>

<p>Letâs look at a concrete example. Here is how the <em>toggle bold</em> command is
implemented:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">boldCommand</span><span class="o">:</span><span class="w"> </span><span class="kt">Command</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="s2">"bold"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">label</span><span class="o">:</span><span class="w"> </span><span class="s2">"Bold"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">accelerator</span><span class="o">:</span><span class="w"> </span><span class="s2">"CmdOrCtrl+B"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">enabled</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">view</span><span class="p">.</span><span class="nx">editable</span><span class="p">,</span>
<span class="w">    </span><span class="nx">active</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">isRangeAllBold</span><span class="p">(</span><span class="nx">view</span><span class="p">.</span><span class="nx">state</span><span class="p">),</span>
<span class="w">    </span><span class="nx">execute</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">toggleBold</span><span class="p">(</span><span class="nx">view</span><span class="p">.</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">view</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">),</span>
<span class="p">};</span>
</pre></div>

<p>We covered <code>isRangeAllBold()</code> and <code>toggleBold()</code> in the <a href="https://vladris.com/blog/2025/04/04/devlog-2-formatting.html">previous
post</a>. Note that
they both need references to the ProseMirror document state and <code>toggleBold()</code>
also needs a way to dispatch transactions, so this <code>Command</code> is defined inside
the editor code.</p>

<p>An editor instance will have an associated command registry. Flow initializes
the editor with a <code>boot()</code> function:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">boot</span><span class="p">(</span><span class="nx">element</span><span class="o">:</span><span class="w"> </span><span class="kt">HTMLElement</span><span class="p">,</span><span class="w"> </span><span class="nx">options?</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorOptions</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">state</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">EditorState</span><span class="p">.</span><span class="nx">create</span><span class="p">({</span>
<span class="w">        </span><span class="cm">/* ... */</span>
<span class="w">    </span><span class="p">});</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">view</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">EditorView</span><span class="p">(</span><span class="nx">element</span><span class="p">,</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">state</span><span class="p">,</span>
<span class="w">        </span><span class="nx">attributes</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="cm">/* ... */</span>
<span class="w">        </span><span class="p">},</span>
<span class="w">    </span><span class="p">});</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">commandRegistry</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">CommandRegistry</span><span class="p">();</span>
<span class="w">    </span><span class="nx">initializeEditorCommands</span><span class="p">(</span><span class="nx">view</span><span class="p">,</span><span class="w"> </span><span class="nx">commandRegistry</span><span class="p">);</span>
<span class="w">    </span><span class="nx">view</span><span class="p">.</span><span class="nx">commandRegistry</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">commandRegistry</span><span class="p">;</span>

<span class="w">    </span><span class="cm">/* ... */</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">editorContext</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">view</span><span class="p">,</span>
<span class="w">        </span><span class="nx">commandRegistry</span><span class="p">,</span>

<span class="w">        </span><span class="cm">/* ... */</span>
<span class="w">    </span><span class="p">};</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">editorContext</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>When we boot an editor instance, we first create a <code>state</code> and a <code>view</code> - this
is standard in ProseMirror. Next, we instantiate a <code>CommandRegistry</code>, initialize
it, and tack it on to the view. This snipped omits some extra stuff that happens
during boot as itâs not the focus of this post. We create an <code>editorContext</code>
which we return to whoever initialized our editor, including the <code>view</code> and the
<code>commandRegistry</code>.</p>

<p>The <code>initializeEditorCommands()</code> function is straight-forward: it consists of a
bunch of command definitions like the <code>boldCommand</code> we saw above and calls to
<code>commandRegistry.register()</code>. This popoulates the registry with all the editor
commands.</p>

<h2>Inter-process communication</h2>

<p>We also need to ensure <code>emitUpdate()</code> is called whenever the editor state
changes. For example, if the selection moves from normal text to bolded text,
the <code>boldCommand</code>'s <code>active()</code> will return <code>true</code>, so the menu bar entry for
<code>Bold</code> should show a checkmark next to it. But because the MacOS menu lives on
the main process, we can't evaluate <code>active()</code> there, rather we need to
serialize all commands into <code>CommandData</code> and pass them from the render process
to the main process. We evaulate <code>active()</code> during serialization. <code>emitUpdate()</code>
lets the app know state changed so it should update the main process.</p>

<p>To ensure we always call <code>emitUpdate()</code> on editor state changes, we can replace
the ProseMirror view's <code>dispatch</code> with an updated version:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">originalDispatch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">view</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">view</span><span class="p">);</span>
<span class="nx">view</span><span class="p">.</span><span class="nx">dispatch</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">originalDispatch</span><span class="p">(</span><span class="nx">tr</span><span class="p">);</span>
<span class="w">    </span><span class="nx">commandRegistry</span><span class="p">.</span><span class="nx">emitUpdate</span><span class="p">();</span>
<span class="p">};</span>
</pre></div>

<p>The view's <code>dispatch()</code> function is how all transactions are applied to the
document state, so this is a good choke point to catch all state changes.</p>

<p>Then we can use the Electron API to send the serialized menu to the main
process:</p>
<div class="highlight"><pre><span/><span class="nx">commandRegistry</span><span class="p">.</span><span class="nx">onUpdate</span><span class="p">(()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nb">window</span><span class="p">.</span><span class="nx">electronAPI</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">UPDATE_MENU</span><span class="p">,</span><span class="w"> </span><span class="nx">commandRegistry</span><span class="p">.</span><span class="nx">getCommandData</span><span class="p">());</span>
<span class="p">});</span>
</pre></div>

<p><code>window.electronAPI</code> is a standard way to set up inter-process communication
in an Electron app. the <code>electronAPI</code> object is made available on the browser
window. It looks like this:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="nb">global</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">interface</span><span class="w"> </span><span class="nx">Window</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">electronAPI</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">send</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">channel</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">data</span><span class="o">:</span><span class="w"> </span><span class="kt">any</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">            </span><span class="nx">on</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">channel</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">...args</span><span class="o">:</span><span class="w"> </span><span class="kt">any</span><span class="p">[])</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">            </span><span class="cm">/* ... */</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>send()</code> passes data to the main process while <code>on()</code> is called when the main
process wants to talk to the render process. In our case, we call <code>send()</code> with
<code>UPDATE_MENU</code> and the serialized command registry. <code>UPDATE_MENU</code> is just a
constant agreed upon by both processes.</p>

<p>End-to-end, the system works like this:</p>

<ul>
<li>The user moves the cursor on bold text.</li>
<li>Moving the cursor is a transaction in ProseMirror, so the view's <code>dispatch()</code>
function ends up being invoked. Our updated version of <code>dispatch()</code> calls
<code>commandRegistry.emitUpdate()</code> internally.</li>
<li>The event handler will get called, and it will <code>send()</code> an <code>UPDATE_MENU</code> to
the main process, passing it a serialized command registry.</li>
<li>When serializing the command registry, <code>active()</code> is evaluated for each
command and serialized to a boolean. For <code>boldCommand</code>, this will now change
from <code>false</code> to <code>true</code>.</li>
<li>The menu bar will be updated on the main process to show a checkmark next to
the <code>Bold</code> menu item.</li>
</ul>

<p>And the other way around, on the render process we listen for <code>EXECUTE_COMMAND</code>:</p>
<div class="highlight"><pre><span/><span class="nb">window</span><span class="p">.</span><span class="nx">electronAPI</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="nx">EXECUTE_COMMAND</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">commandId</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">commandRegistry</span><span class="p">.</span><span class="nx">getCommand</span><span class="p">(</span><span class="nx">commandId</span><span class="p">)</span><span class="o">!</span><span class="p">.</span><span class="nx">execute</span><span class="p">();</span>
<span class="p">});</span>
</pre></div>

<p>When the user selects <code>Bold</code> from the menu bar, the main process will send an
<code>EXECUTE_COMMAND</code> to the render thread, with the <code>boldCommand</code> as <code>commandId</code>.
The render process will call the command's <code>execute()</code> function, which, in this
case, will call <code>toggleBold()</code>.</p>

<p>As of now, we serialize and transfer the whole command registry on each state
change. There are probably more efficient ways of doing this, but the current
implementation is simple and the frequency of updates is low enough (on editor
state changes, meaning on user input) that I'm not concerned about the
performance impact of this approach.</p>

<h2>Additional commands</h2>

<p>The editor's host can add its own commands to this registry. For example, Flow
hooks up the mode change commands. Here's <code>focusMode</code>:</p>
<div class="highlight"><pre><span/><span class="nx">commandRegistry</span><span class="p">.</span><span class="nx">register</span><span class="p">({</span>
<span class="w">    </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="s2">"focusMode"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">label</span><span class="o">:</span><span class="w"> </span><span class="s2">"Focus Mode"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">enabled</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kc">true</span><span class="p">,</span>
<span class="w">    </span><span class="nx">active</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">modeRef</span><span class="p">.</span><span class="nx">current</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"FocusMode"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">execute</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">setMode</span><span class="p">(</span><span class="s2">"FocusMode"</span><span class="p">);</span>
<span class="w">    </span><span class="p">},</span>
<span class="p">});</span>
</pre></div>

<p>Where <code>modeRef</code> here is a React ref to the curent mode. </p>

<p>The distinction here is that the editor commands (like <code>boldCommand</code>) are
registered by the editor itself on boot via <code>initializeEditorCommands()</code>. Then
the host adds more commands to the registry, like <code>foucsMode</code>, which don't
directly impact the editor state.</p>

<h2>Commanding surfaces</h2>

<p>We have a <code>commandRegistry</code> which we keep up to date with the editor's state
and synchronized with the main process. Why do we need a centralized registry?
Because the same commands can appear in different places. So far we only talked
about the app menu bar, but that is not the only commanding surface.</p>

<p>Flow also has a context menu. Right-clicking inside the editor will pop over
a context menu with a subset of the commands. <code>Bold</code> is one of them too. One
advantage of the centralized <code>commandRegistry</code> is that both the app menu bar
and the context menu get their data from the same source. So if <code>Bold</code> should
have a checkmark next to it (selection is on bold text), then the checkmark
will show up consistently across the app menu bar and the context menu.</p>

<p>Not yet implemented in Flow, but coming soon: a toolbar. A toolbar would also
source it's state from the <code>commandRegistry</code>. The same way we determine whether
to show a checkmark next to the <code>Bold</code> menu entry based on the <code>active</code>
property, we would determine whether to show the <code>Bold</code> toolbar button
depressed.</p>

<p>The shared <code>commandRegistry</code> will ensure the commands look and behave the same
regardless of where they are surfaced.</p>

<h2>Summary</h2>

<p>In this post I covered commanding and how Flow implements it.</p>

<ul>
<li><code>Command</code> objects represent commands.</li>
<li>The <code>CommandRegistry</code> collects these into a catalog that can be serialized (to
be sent between processes) and that can notify listeners of changes.</li>
<li>We automated emitting updates by modifying the ProseMirror view's
<code>dispatch()</code> method.</li>
<li>We looked at how Electron handles inter-process communication (via <code>send()</code>
and <code>on()</code>) and how we're using these with the commands.</li>
<li>We talked about commanding surfaces and how the common registry can be used
across different UI controls like app menu bar, context menu, and toolbars.</li>
</ul>

<p>This was the second part of the <em>formatting and commanding</em>. In the <a href="https://vladris.com/blog/2025/04/04/devlog-2-formatting.html">previous
post</a> I covered
how formatting is implemented inside the editor, while in this post we went over
the layer on top of that - how formatting actions are represented as commands,
kept in sync with the editor state, and surfaced in the UI.</p>

<p>Flow is now available on the <a href="https://apps.apple.com/us/app/flow-by-saturn9/id6744873955?mt=12">Mac App
Store</a>.</p>
]]></description>
      <pubDate>Thu, 08 May 2025 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/04/04/devlog-2-formatting.html</link>
      <guid>https://vladris.com/blog/2025/04/04/devlog-2-formatting.html</guid>
      <title><![CDATA[DevLog 2: Formatting]]></title>
      <description><![CDATA[<h1>DevLog 2: Formatting</h1>

<p>One of the more interesting (and generally applicable) things I had to build for
<a href="https://saturn9.studio/flow/">Flow</a> is the commanding infrastructure,
especially as it pertains to formatting. This entails going from the app UI all
the way down to the editor and vice-versa.</p>

<p>What I mean by this is, the user can apply a command like <em>toggle bold on the
current selection</em> in multiple ways: using the <code>Cmd+B</code> keyboard shortcut, or via
the menu bar, going to <code>Format -&gt; Bold</code>, or via the context menu. I did not
implement a toolbar for Flow to keep the UI clean, but that could also be an
option.</p>

<p>Not only that, the menu and context menu should show a checkmark next to the
<code>Bold</code> command if the current selection covers only bold text. Similarly, a
toolbar button would show as pressed when the current selection covers only bold
text. This is standard behavior for a text editor.</p>

<p>I call this the <em>commanding infrastructure</em>: a way for the editor to expose a
set of commands like <em>toggle bold on the current selection</em>, including any
additional state required (like whether <code>Bold</code> should show a checkmark/pressed
button or not; keyboard shortcut etc.). This infrastructure needs to ensure all
the different UI entry points are views on the same state, and all invoke the
same editor behavior. This state needs to propagate from the editor to the UI
layer, since only the editor <q>knows</q> whether the text the user is currently on
is bold or not. Then the different UI entry points need a way to tell the editor
to make some change, e.g. <em>toggle bold on the current selection</em>.</p>

<p>An instruction like the above does <em>formatting</em>. Formatting includes changing
the content by applying properties like bold, italic, underline etc., turning a
paragraph into a header, a blockquote, a list item, and so on. There is quite a
lot of complexity to even something simple like <em>toggle bold on the current
selection</em>. I'll focus on this complexity in this blog post and I will cover
commanding in the next post.</p>

<h2>Bolding text</h2>

<p>Since Flow uses Markdown, making some text bold means adding <code>**</code> markers around
it. Conversely, removing bold means removing the <code>**</code> surrounding markers.</p>

<p>This sounds pretty straight-forward, but there are many special cases that a
well-behaved editor needs to handle properly:</p>

<h3>No selection</h3>

<p>If the user doesn't have a selection, just the cursor:</p>

<ul>
<li>If the cursor is not on a word, rather on whitespace, toggling bold should add
<code>**</code> before and <code>**</code> after the cursor.</li>
<li>If the cursor is on a word that is not bold, toggling bold should mark that word as bold.</li>
<li>If the cursor is on a word that is bold, toggling bold should, depending on
the editor, remove bold only from that word or for from the whole span. If the
cursor is somewhere over <code>sentence</code> in <code>**This sentence is bold**</code>, depending
on the editor you might end up with <code>**This** sentence **is bold**</code> or <code>This
sentence is bold</code>.</li>
</ul>

<h3>Selection spanning bold/not bold</h3>

<p>If all the selected text is bold, then toggling it should remove the bold
markup. Otherwise, if at least some of the selected text is not bold, toggling
should make it all bold.</p>

<p>Selecting <code>**Some of this** text is bold</code> and applying bold to it should yield
<code>**Some of this text is bold**</code>, extending the bold markup to cover the whole
span.</p>

<p>What about removing bold? I've seen different editors also handle this
differently. If <code>[</code> and <code>]</code> denote the selection, what should happen when the
user toggles bold on <code>**Some of [this text] is bold**</code>? Some editors yield <code>Some
of this text is bold</code>, removing the whole markup, while others remove it only
from the selection, so you end up with <code>**Some of** this text **is bold**</code>.</p>

<p>Note we also need to be smart about cleaning up markup. If we toggle bold on
<code>[**Some of** this text **is bold**]</code>, we could naively do something like
<code>**Some of** **this text** **is bold**</code> but instead we should account for this
and end up with a cleaner <code>**Some of this text is bold**</code>.</p>

<h3>Selection spanning paragraphs</h3>

<p>Markdown markup like <code>**</code> cannot span multiple paragraphs. If the user selects
multiple paragraphs, we need to apply the same logic to each paragraph in turn.
We can just add <code>**</code> at the beginning and end of the selection, rather we need
to add a <code>**</code> at the end of each selected paragraph except the last one in the
selection and add a <code>**</code> at the beginning of each selected paragraph except the
first on in the selection.</p>
<div class="highlight"><pre><span/>This is a [multiple

paragraph text with selection

spanning multiple paragraphs] too
</pre></div>

<p>Toggling bold here should yield</p>
<div class="highlight"><pre><span/>This is a **multiple**

**paragraph text with selection**

**spanning multiple paragraphs** too
</pre></div>

<p>We also need to take into account whether all the text in the selection, across
paragraphs, is bold or not, so we know whether you need to toggle it on or off.</p>

<p>For example:</p>
<div class="highlight"><pre><span/>This is a [**multiple**

**paragraph** text **with selection**

**spanning multiple paragraphs**] too
</pre></div>

<p>If <code>[</code> and <code>]</code> denote the selection, applying bold to this should leave the
first and last paragraphs unchanged, since the selection in both is fully over
bold text. The only change should happen in the middle paragraph, which should
be fully bolded:</p>
<div class="highlight"><pre><span/>This is a **multiple**

**paragraph text with selection**

**spanning multiple paragraphs** too
</pre></div>

<p>These are all various situations we need to account for when implementing
formatting.</p>

<p>In fact, formatting is an area where I have the most unit test coverage and I
keep adding tests as I uncover various cases.</p>

<h2>ProseMirror implementation</h2>

<p>I'll cover how I implemented formatting. My editor is built on top of
<a href="https://prosemirror.net/">ProseMirror</a>, and I will not go to deep into
explaining how ProseMirror itself works. For that, refer to the
<a href="https://prosemirror.net/docs/">documentation</a>.</p>

<h3>Ranges and Decorations</h3>

<p>Formatting is based on <em>Ranges</em> and <em>Decorations</em>. A <em>Range</em> simply defines a
range within the document, with <code>from</code> a <code>to</code> locations:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">Range</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">from</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="w">    </span><span class="nx">to</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p><em>Decoration</em> is a ProseMirror concept<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. A plugin<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup> can add decorations to
the document, which are usually consumed by the view. A decoration contains
<code>from</code> and <code>to</code> positions in the document, a <code>spec</code> of type <code>any</code> to store
arbitrary information, and a set of <em>decoration attributes</em> which translate into
DOM node attributes when the document gets rendered. For example, if we select a
range in <code>"this **is a** string"</code>, say the <code>**is a**</code> part and set as attribute
<code>class</code> as <code>"bold"</code>, it will translate this as HTML into <code>this &lt;span
class="bold"&gt;**is a**&lt;/span&gt; string</code>.</p>

<p>I have a Markdown plugin that parses the document and generates the appropriate
decorations. That's a topic for another post. For formatting, we simply consume
the produced decorations. One of the core functions fetches the decorations
produced by the Markdown plugin:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">getDecorations</span><span class="p">(</span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">DecorationSet</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">plugin</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">plugins</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span>
<span class="w">        </span><span class="p">(</span><span class="nx">plugin</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">plugin</span><span class="p">.</span><span class="nx">spec</span><span class="p">.</span><span class="nx">key</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">markdownPluginKey</span>
<span class="w">    </span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">pluginState</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">plugin</span><span class="o">?</span><span class="p">.</span><span class="nx">getState</span><span class="p">(</span><span class="nx">state</span><span class="p">);</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">pluginState</span><span class="o">?</span><span class="p">.</span><span class="nx">decorations</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">DecorationSet</span><span class="p">.</span><span class="nx">empty</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This is very ProseMirror-specific: we take an <code>EditorState</code> which represents the
state of the document, retrieve the Markdown plugin, get its state, then fetch
the decorations from the state.</p>

<p>Now that we can access the full set of decorations, we need a few more helper
functions to deal with selection ranges:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">isRangeDecorated</span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">className</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">from?</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">,</span>
<span class="w">    </span><span class="nx">to?</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="kr">from</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="nx">to</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kr">from</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">selection</span><span class="p">.</span><span class="kr">from</span><span class="p">;</span>
<span class="w">        </span><span class="nx">to</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">selection</span><span class="p">.</span><span class="nx">to</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">decoration</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">getDecorations</span><span class="p">(</span><span class="nx">state</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="kr">from</span><span class="p">,</span><span class="w"> </span><span class="nx">to</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">((</span><span class="nx">decoration</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">any</span><span class="p">).</span><span class="kr">type</span><span class="o">?</span><span class="p">.</span><span class="nx">attrs</span><span class="o">?</span><span class="p">.</span><span class="kd">class</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">className</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This function helps us check whether the given range is decorated with the given
class name. A decoration can have any attributes on it, but Flow uses class
names to tag things as bold, italic, etc. This functions tells us whether the
given class name appears anywhere within the selection. In other words, this
returns <code>true</code> if any part of the range is decorated.</p>

<p>It will return <code>true</code> if we query for <code>bold</code> and the selection range yields
<code>this **is a** string</code> since <code>**is a**</code> should have the decoration.</p>

<p>We also need a function that tells us whether a range is fully covered:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">isRangeCovered</span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">className</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">from?</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">,</span>
<span class="w">    </span><span class="nx">to?</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="kr">from</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="nx">to</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kr">from</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">selection</span><span class="p">.</span><span class="kr">from</span><span class="p">;</span>
<span class="w">        </span><span class="nx">to</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">selection</span><span class="p">.</span><span class="nx">to</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">decoration</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">getDecorations</span><span class="p">(</span><span class="nx">state</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="kr">from</span><span class="p">,</span><span class="w"> </span><span class="nx">to</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">((</span><span class="nx">decoration</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">any</span><span class="p">).</span><span class="kr">type</span><span class="o">?</span><span class="p">.</span><span class="nx">attrs</span><span class="o">?</span><span class="p">.</span><span class="kd">class</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">className</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">continue</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">decoration</span><span class="p">.</span><span class="kr">from</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">decoration</span><span class="p">.</span><span class="nx">to</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="nx">to</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This returns <code>true</code> if a decoration covers the full range. This will return
<code>false</code> for <code>bold</code> and <code>this **is a** string</code>, since the bold decoration only
covers <code>**is a**</code> rather than the whole range.</p>

<p>Now here is where things get a bit more interesting: a selection range can span
multiple paragraphs, but Markdown markup cannot. As we saw above, we could have
a selection that spans the following 3 paragraphs:</p>
<div class="highlight"><pre><span/>This is a **multiple**

**paragraph text with selection**

**spanning multiple paragraphs** too
</pre></div>

<p>Note that all text starting from <code>**multiple**</code> on the first paragraph all the
way down to <code>paragraphs**</code> on the last line is bold, but we need some markup on
each line because of how Markdown works. In other words, we need to treat each
paragraph separately. The following function generates an array of ranges from
the current selection:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">getRangesFromSelection</span><span class="p">(</span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kr">from</span><span class="p">,</span><span class="w"> </span><span class="nx">to</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">selection</span><span class="p">;</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">ranges</span><span class="o">:</span><span class="w"> </span><span class="kt">Range</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="nx">state</span><span class="p">.</span><span class="nx">doc</span><span class="p">.</span><span class="nx">nodesBetween</span><span class="p">(</span><span class="kr">from</span><span class="p">,</span><span class="w"> </span><span class="nx">to</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">node</span><span class="p">,</span><span class="w"> </span><span class="nx">pos</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="kr">type</span><span class="p">.</span><span class="nx">name</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"paragraph"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">paragraphStart</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">pos</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">paragraphEnd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">pos</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">node</span><span class="p">.</span><span class="nx">nodeSize</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>

<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">rangeFrom</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">max</span><span class="p">(</span><span class="kr">from</span><span class="p">,</span><span class="w"> </span><span class="nx">paragraphStart</span><span class="p">);</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">rangeTo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">min</span><span class="p">(</span><span class="nx">to</span><span class="p">,</span><span class="w"> </span><span class="nx">paragraphEnd</span><span class="p">);</span>

<span class="w">            </span><span class="nx">ranges</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
<span class="w">                </span><span class="nx">from</span><span class="o">:</span><span class="w"> </span><span class="kt">rangeFrom</span><span class="p">,</span>
<span class="w">                </span><span class="nx">to</span><span class="o">:</span><span class="w"> </span><span class="kt">rangeTo</span><span class="p">,</span>
<span class="w">            </span><span class="p">});</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">});</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">ranges</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>We first get the <code>from</code> and <code>to</code> of the selection from the editor state. We then
iterate through each document node between <code>from</code> and <code>to</code>. For nodes of type
<code>paragraph</code>, we get the adjusted start and end positions (ProseMirror inserts an
additional position before and after each node, which we need to account for),
and determine the start and end of the selection range within this paragraph.</p>

<p>This function effectively turns a single <code>from</code>-<code>to</code> selection into several
ranges, one for each paragraph.</p>

<p>We already saw the <code>isRangeDecorated</code> and <code>isRangeCovered()</code> functions. I
implemented a couple of additional helpers, <code>areAllRangesDecorate()</code> and
<code>areAllRangesCovered()</code> which simply check whether all of the ranges returned by
<code>getRangesFromSelection</code> are decorated or covered by the given markup. The
implementation is trivial.</p>

<p>With these pieces in place, we can look at how Flow toggles formatting for the
current user selection.</p>

<h3>Toggling Formatting</h3>

<p>Let's start with the core formatting functions, <code>markRange()</code> and
<code>unmarkRange()</code>.</p>

<p><code>markRange()</code> takes a selection range and ensures it gets fully covered by the
given markup. For example, if we take the <code>this is a string</code> range, running
<code>markRange()</code> on it with the <code>**</code> markup will yield <code>**this is a string**</code>. But
that's not all! If instead we run it on <code>this **is a** string</code>, it will also
yield <code>**this is a string**</code>. Note we are effectively selecting text that is
partially bolded, and we turn it all bold - that entails not only adding <code>**</code> at
both ends, but also removing the inner-markup.</p>

<p>More than that, we also need to handle a case like the following (where <code>[]</code>
represents the user selection): <code>this **is [a** string]</code>. Making this selection
bold should yield <code>this **is a string**</code>. Not only we remove the inner markup,
we also need to be smart enough to know we already have bold markup before the
selection starts, so we shouldn't prepend <code>**</code>.</p>

<p>Here is the full implementation of <code>markRange()</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">markRange</span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">,</span>
<span class="w">    </span><span class="nx">className</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">markup</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="kt">Range</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">markupLocations</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">leadingMarkup</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">trailingMarkup</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">markupRange</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">getMarkupRangesForRange</span><span class="p">(</span>
<span class="w">        </span><span class="nx">state</span><span class="p">,</span>
<span class="w">        </span><span class="nx">className</span><span class="p">,</span>
<span class="w">        </span><span class="nx">range</span>
<span class="w">    </span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="kr">from</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nx">range</span><span class="p">.</span><span class="kr">from</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">leadingMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">markupLocations</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="kr">from</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="nx">to</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">trailingMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">markupLocations</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="nx">to</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">markup</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">tr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">removeMarkupAtLocations</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">tr</span><span class="p">,</span><span class="w"> </span><span class="nx">markup</span><span class="p">,</span><span class="w"> </span><span class="nx">markupLocations</span><span class="p">);</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">leadingMarkup</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">tr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">insertMarkupAtPos</span><span class="p">(</span><span class="nx">tr</span><span class="p">,</span><span class="w"> </span><span class="nx">markup</span><span class="p">,</span><span class="w"> </span><span class="nx">tr</span><span class="p">.</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">range</span><span class="p">.</span><span class="kr">from</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">trailingMarkup</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">tr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">insertMarkupAtPos</span><span class="p">(</span><span class="nx">tr</span><span class="p">,</span><span class="w"> </span><span class="nx">markup</span><span class="p">,</span><span class="w"> </span><span class="nx">tr</span><span class="p">.</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">tr</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This leverages several helper functions which I won't walk through in the
interest of time, but will explain what each does.</p>

<p>The function takes the following arguments: an editor state, a <em>transaction</em>,
the class name for the formatting as given by the decorations produced by the
Markdown plugin (e.g. <code>bold</code> for bold), the markup itself (e.g. <code>**</code> for bold),
and a range.</p>

<p>I haven't talked about transactions yet. Transactions is how ProseMirror handles
updates to the document state<sup id="fnref3"><a href="#fn3" rel="footnote">3</a></sup>. Any change to the document needs to come in
the form of a transaction. A transaction can accumulate several operations
before being applied to the document. This architecture ensures consistency of
the editor state: if the state changes for whatever reason between the time a
transaction was created and the time it is dispatched, it will fail. This saves
us from dealing with issues like selection changing <em>while</em> we're trying to do
something to it which would result in unexpected results. Since all state
mutations come via transactions, ProseMirror will know when it needs to re-run
plugins - for example the Markdown plugin needs to run whenever the content of
the document changes to ensure our decorations are up to date with the text.
That's why all our formatting functions take a transaction as argument, to which
they add operations. To apply a transaction to the document, we need a
<em>dispatch</em> function which ProseMirror provides.</p>

<p>Back to <code>markRange()</code>, we first call <code>getMarkupRangesForRange()</code>. This is a
helper function that returns all the <code>from</code>-<code>to</code> ranges of all decorations with
the given class name intersecting our <code>range</code>. The <em>intersecting</em> part is
important: if can return ranges that partially overlap the range, fully cover
it, or are within it. I won't go over the implementation but it is
straightforward - it simply takes this data from the decorations produced by the
Markdown plugin.</p>

<p>For reach of the returned markup ranges, if the markup range starts outside our
range, we mark <code>leadingMarkup</code> as <code>true</code>, otherwise we keep track of the start
location of this markup range:</p>
<div class="highlight"><pre><span/><span class="err">â¦</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="kr">from</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nx">range</span><span class="p">.</span><span class="kr">from</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">leadingMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">markupLocations</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="kr">from</span><span class="p">);</span>
<span class="p">}</span>
<span class="err">â¦</span>
</pre></div>

<p>We do the same for the end of the markup ranges:</p>
<div class="highlight"><pre><span/><span class="err">â¦</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="nx">to</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">trailingMarkup</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">markupLocations</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="nx">to</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">markup</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="p">}</span>
<span class="err">â¦</span>
</pre></div>

<p>Now we should have the locations of all markup inside our range, for example the
locations of all <code>**</code> inside the range we're trying to turn bold. We should also
know whether we have <code>leadingMarkup</code> and/or <code>trailingMarkup</code>, that is whether
there already is a leading <code>**</code> before or a trailing <code>**</code> after our range.</p>

<p>The next step is to remove all markup inside the selection - as a reminder, if
the user selects <code>this **is a** string</code> and wants to turn all of it bold, we
need to get rid of the markup around <code>is a</code> and the end result should be <code>**this
is a string**</code>. Since we already have all markup locations, <code>markRange()</code> calls
another helper function, <code>removeMarkupAtLocations()</code>:</p>
<div class="highlight"><pre><span/><span class="err">â¦</span>
<span class="nx">tr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">removeMarkupAtLocations</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">tr</span><span class="p">,</span><span class="w"> </span><span class="nx">markup</span><span class="p">,</span><span class="w"> </span><span class="nx">markupLocations</span><span class="p">);</span>
<span class="err">â¦</span>
</pre></div>

<p>This helper function takes the editor state, a transaction, the markup we're
trying to remove and where it is located in the selection, then proceeds to
remove it. Finally, in case we don't have leading and/or trailing markup, we
need to insert it:</p>
<div class="highlight"><pre><span/><span class="err">â¦</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">leadingMarkup</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">tr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">insertMarkupAtPos</span><span class="p">(</span><span class="nx">tr</span><span class="p">,</span><span class="w"> </span><span class="nx">markup</span><span class="p">,</span><span class="w"> </span><span class="nx">tr</span><span class="p">.</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">range</span><span class="p">.</span><span class="kr">from</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">trailingMarkup</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">tr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">insertMarkupAtPos</span><span class="p">(</span><span class="nx">tr</span><span class="p">,</span><span class="w"> </span><span class="nx">markup</span><span class="p">,</span><span class="w"> </span><span class="nx">tr</span><span class="p">.</span><span class="nx">mapping</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">range</span><span class="p">.</span><span class="nx">to</span><span class="p">));</span>
<span class="p">}</span>
<span class="err">â¦</span>
</pre></div>

<p>And that's it. The transaction we end up with contains all required edits to
properly mark the given range.</p>

<p>The inverse of this is <code>unmarkRange()</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">unmarkRange</span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">,</span>
<span class="w">    </span><span class="nx">className</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">markup</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">range</span><span class="o">:</span><span class="w"> </span><span class="kt">Range</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">markupLocations</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">markupRange</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">getMarkupRangesForRange</span><span class="p">(</span>
<span class="w">        </span><span class="nx">state</span><span class="p">,</span>
<span class="w">        </span><span class="nx">className</span><span class="p">,</span>
<span class="w">        </span><span class="nx">range</span>
<span class="w">    </span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">markupLocations</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="kr">from</span><span class="p">);</span>
<span class="w">        </span><span class="nx">markupLocations</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">markupRange</span><span class="p">.</span><span class="nx">to</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">markup</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">removeMarkupAtLocations</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">tr</span><span class="p">,</span><span class="w"> </span><span class="nx">markup</span><span class="p">,</span><span class="w"> </span><span class="nx">markupLocations</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>This function is simpler than mark range. It also relies on
<code>getMarkupRangesForRange()</code> and stores all markup locations. As a reminder,
<code>getMarkupRangesForRange()</code> will include markups that intersect the range, so
even if the selection is inside a bolded range, like <code>**This [is a] string**</code>,
we would still get the locations of the two <code>**</code> markups.</p>

<p>Once we have these, we simply remove all markup by calling
<code>removeMarkupAtLocations()</code>. It turns out that removing markup is easier that
adding it.</p>

<p>The user issues the same command, <em>toggle bold</em>, and we need to figure out
whether we should add or remove the markup. We do this by relying on
<code>areAllRangesCovered()</code> which we described above. The <code>toggleDecoration()</code>
function takes an editor state, a dispatch function, a class name (like <code>bold</code>)
and a markup (like <code>**</code>). The function begins with:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">toggleDecoration</span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">dispatch</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">,</span>
<span class="w">    </span><span class="nx">className</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">markup</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">ranges</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getRangesFromSelection</span><span class="p">(</span><span class="nx">state</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">shouldToggleOn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">!</span><span class="nx">areAllRangesCovered</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">ranges</span><span class="p">,</span><span class="w"> </span><span class="nx">className</span><span class="p">);</span>
<span class="err">â¦</span>
</pre></div>

<p>We first get the user selection from the state and map it to one or more ranges
(to account for selections that span paragraphs). Next, if at least one of the
selected ranges is not fully covered by the relevant decoration (e.g. <code>bold</code>),
then we know we should toggle bold <em>on</em> across all ranges. Otherwise, if all
ranges are fully covered, we need to toggle bold <em>off</em>.</p>

<p>There's a bit more logic in this function which I won't go over that handles the
special case of not having a selection. If we only have a cursor, the expected
behavior is as follows: if the cursor is inside a marked range, e.g. inside a
bold range, toggling bold should remove the bold markup of that range. Note this
could be a word, a sentence, or even a whole paragraph. On the other hand, if
the cursor is not inside a marked range, the expected behavior is to apply the
markup just on the word the cursor is on. Try it out in your favorite editor, it
should behave like this!</p>

<p>One more special case: if the cursor is not on a word, rather on whitespace, the
expectation is to add markup around it, so for bold, we would add a <code>**</code> right
before the cursor and a <code>**</code> right after.</p>

<p>I will skip over the logic of identifying word boundaries and such, but that's
the bulk of the extra code in <code>toggleDecoration()</code>. Once we we know all the
ranges we need to toggle formatting for, and we know whether we need to toggle
it <em>on</em> or <em>off</em>, we simply call <code>markRange()</code> or <code>unmarkRange()</code> for each of
these ranges.</p>

<p>I used bold as an example throughout this post, but as you can see, the
functions are generic enough to apply to any type of inline formatting: bold,
italic, underline, etc. In fact, I have a bunch of functions wrapping these:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">toggleBold</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">dispatch</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">toggleDecoration</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">dispatch</span><span class="p">,</span><span class="w"> </span><span class="s2">"strong"</span><span class="p">,</span><span class="w"> </span><span class="s2">"**"</span><span class="p">);</span>

<span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">toggleItalic</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">dispatch</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">toggleDecoration</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">dispatch</span><span class="p">,</span><span class="w"> </span><span class="s2">"em"</span><span class="p">,</span><span class="w"> </span><span class="s2">"*"</span><span class="p">);</span>

<span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">toggleUnderline</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">dispatch</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">toggleDecoration</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">dispatch</span><span class="p">,</span><span class="w"> </span><span class="s2">"underline"</span><span class="p">,</span><span class="w"> </span><span class="s2">"~"</span><span class="p">);</span>

<span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">toggleStrikethrough</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">dispatch</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">toggleDecoration</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">dispatch</span><span class="p">,</span><span class="w"> </span><span class="s2">"strikethrough"</span><span class="p">,</span><span class="w"> </span><span class="s2">"~~"</span><span class="p">);</span>

<span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">toggleHighlight</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">dispatch</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">toggleDecoration</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">dispatch</span><span class="p">,</span><span class="w"> </span><span class="s2">"highlight"</span><span class="p">,</span><span class="w"> </span><span class="s2">"=="</span><span class="p">);</span>

<span class="k">export</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">toggleCode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">state</span><span class="o">:</span><span class="w"> </span><span class="kt">EditorState</span><span class="p">,</span>
<span class="w">    </span><span class="nx">dispatch</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">tr</span><span class="o">:</span><span class="w"> </span><span class="kt">Transaction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">toggleDecoration</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">dispatch</span><span class="p">,</span><span class="w"> </span><span class="s2">"code"</span><span class="p">,</span><span class="w"> </span><span class="s2">"`"</span><span class="p">);</span>
</pre></div>

<p>The app can invoke a command like <em>toggle bold</em> by calling the corresponding
<code>toggleBold()</code> function. Note everything is neatly wrapped in this function,
the caller just needs to pass in an editor state and a way to apply,
transactions, both being easy to get from an editor view.</p>

<p>Conversely, if we need to know whether the Bold button in a hypothetical toolbar
(at the time of writing, Flow doesn't have a toolbar) should render as pressed
or not, or whether the app menu or context menu should show a checkmark next to
the Bold menu item, we need to call <code>isRangeCovered()</code> and check whether the
range is fully bolded or not.</p>

<p>In a future post, I will focus on the commanding part, and how the editor makes
these functions available to the app.</p>

<h2>Block Formatting</h2>

<p>There's more to formatting than what I covered in this post. Especially with
Markdown, but also generalizes quite well to other editors: there's <em>inline</em>
formatting which we just covered, and <em>block</em> formatting.</p>

<p>Inline formatting deals with marking up parts of text in a paragraph.</p>

<p>Block formatting deals with formatting a whole paragraph. Some Markdown examples
of this are:</p>

<ul>
<li>Headings - <code>#</code>, <code>##</code>, etc. at the beginning of a paragraph will make the
whole paragraph be a heading.</li>
<li>Block quotes - <code>&gt;</code> at the beginning of a paragraph will make the whole
paragraph be a block quote.</li>
<li>Code blocks.</li>
<li>Ordered and unordered lists - list handling brings a bunch more complexity,
again a potential topic for its own blog post.</li>
</ul>

<p>Block formatting is actually simpler in most cases than inline formatting - the
markers are always at the beginning of the paragraph and the logic to determine
whether toggling means toggling <em>on</em> or <em>off</em> is also simpler.</p>

<p>List handling is in general more complex, especially if we need to support
things like nested lists and be smart about, for example, automatically
incrementing the numbering on a numbered list. That said, this has less to do
with formatting and more with how lists work.</p>

<h2>Summary</h2>

<p>In this post, I covered some interesting aspects of how formatting works in an
editor (and what users would expect from a well-behaved editor):</p>

<ul>
<li>Toggling formatting <em>on</em> or <em>off</em> depending on the selection.</li>
<li>Handling selection overlapping a mix of marked and unmarked text.</li>
<li>Handling selection spanning multiple paragraphs by handling each paragraph
separately.</li>
</ul>

<p>I went over some of my implementation of this for Flow on top of ProseMirror
and introduced a few ProseMirror concepts like editor <em>state</em>, <em>decorations</em>,
and <em>transactions</em>.</p>

<p>Finally, I briefly touched on another, simpler flavor of formatting: <em>block</em>
formatting, which applies to whole paragraphs.</p>

<p>In the next post, I am planning to cover <em>commanding</em>, and how these lower-level
formatting functions can be packaged into a commanding system an app can present
to the user.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>See <a href="https://prosemirror.net/docs/ref/#view.Decorations">https://prosemirror.net/docs/ref/#view.Decorations</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>See <a href="https://prosemirror.net/docs/ref/#state.Plugin_System">https://prosemirror.net/docs/ref/#state.Plugin_System</a>. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

<li id="fn3">
<p>See <a href="https://prosemirror.net/docs/ref/#state.Transaction">https://prosemirror.net/docs/ref/#state.Transaction</a>. <a href="#fnref3" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Fri, 04 Apr 2025 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/03/08/devlog-1-flow.html</link>
      <guid>https://vladris.com/blog/2025/03/08/devlog-1-flow.html</guid>
      <title><![CDATA[DevLog 1: Flow]]></title>
      <description><![CDATA[<h1>DevLog 1: Flow</h1>

<p>I wrote about <a href="https://vladris.com/blog/2024/12/07/notes-on-authoring-tools.html">authoring tools</a> last year and my side project of building an editor. I am now happy to announce the preview release of <a href="https://saturn9.studio/flow/">Flow</a>, a creative writing app.</p>

<p><img src="./blank.png" alt="Screenshot"/></p>

<h2>MVP</h2>

<p>Flow is at MVP state currently, with a bunch of features that I am planning to add later on. The public roadmap is <a href="https://saturn9.studio/flow/roadmap/">here</a>. It does have the basics though: Markdown support with markup hiding when not under the cursor, a full-screen distraction-free mode, automatic file saving, theming, and word count. This is pretty much what I need for a creative writing session, and I hope other authors will find it inspiring too.</p>

<p>It also includes a couple of unique features: a special <code>***</code> horizontal rule that gets rendered as a centered <code>âµ</code> and automatic indentation of paragraphs. This will automatically make the text resemble a print book, which I'm hoping will help with inspiration and motivation.</p>

<p>I did not implement export yet, but copy/paste to Word should work. Copy will put both the raw Markdown text and HTML on the clipboard. Similarly, paste supports conversion from HTML to Markdown.</p>

<p>Flow is currently missing a few popular Markdown features, like support for hyperlinks, images, tables, code blocks etc. but for a creative writing-focused MVP I think that's OK. I'll be adding those soon. Also planning to add export to PDF and Word. Once some of the existing gaps are filled and Flow graduates from Preview, it will move to the App Store. For now it is available as a download.</p>

<p>And that's enough about the product, I promised a DevLog, so let's go over some engineering details. I'll start with a high-level overview and if future posts dig deeper into some of the implementation details.</p>

<p><img src="./focus.png" alt="Screenshot"/></p>

<h2>Architecture</h2>

<p>The core editor is built on <a href="https://prosemirror.net/">ProseMirror</a>, a flexible and extensible web-based editor framework. All editor features are implemented as ProseMirror plugins.</p>

<p>The editor is wrapped in an Electron app. I went for Electron as I do want to make this available across both Mac and Windows and this provides an easy way to do this.</p>

<p>The UI is built with React.</p>

<h3>Core editor</h3>

<p>ProseMirror maintains a clean separation of editor state and view. Changes to the state are done via transactions. Plugins can listen to both view events and state changes and run code to update the document state. On the view side, this means reacting to DOM events like user pasting content into the editor, keypresses etc. State changes include content changes, selection changes and so on.</p>

<p>The editor behind Flow implements multiple plugins to handle anything from decorating Markdown markup (so it can be highlighted or automatically hidden), to providing word count, copy/paste conversion between Markdown and HTML, and many others.</p>

<p>Markdown is an interesting (and foundational) piece for Flow. ProseMirror does support Markdown out-of-the-box via the <a href="https://github.com/ProseMirror/prosemirror-markdown">prosemirror-markdown</a> plugin. This converts Markdown to a rich document schema that includes entities like headings, blockquotes and so on. It also gets rid of the markup. My vision for Flow was a bit different though, so I didn't use this. As I mentioned in the previous post, I want something that behaves more like <a href="https://bear.app/">Bear</a> or <a href="https://obsidian.md/">Obsidian</a>. I wanted all markup to stay in the document, and simply hide when the cursor is not on it. To that end, I ended up using a very simple document schema containing just paragraphs. I parse the markdown using <a href="https://github.com/markdown-it/markdown-it">markdown-it</a>. The <code>markdown-it</code> library parses Markdown text and can render HTML, but since I don't want a full HTML rendering, I'm using only the parser. Instead of converting, say <code>**bold**</code> to <code>&lt;strong&gt;bold&lt;strong&gt;</code>, I just want to annotate the <code>**</code>s to keep track of what is markup and annotate the whole <code>**bold**</code> as something that should be rendered in bold. With this approach, the user is editing the raw Markdown but we can provide appropriate styling based on these annotations (<a href="https://prosemirror.net/docs/ref/#view.Decorations">Decorations</a> in ProseMirror parlance).</p>

<p><img src="./markdown.png" alt="Screenshot"/></p>

<h3>App shell</h3>

<p>Electron is the go-to for bundling web applications as native apps. This was my first time working with Electron, and I was pleasantly surprised by how many things come turnkey with it. Electron makes building and signing an Apple app very easy. I'm also using the electron-updater module which makes auto-updates seamless.</p>

<p>The one thing I didn't realize was how large an Electron bundle is. While the total bundle size of my editor code is only a couple of MBs, the app itself gets to be around 500 MBs compressed to around 170 MBs dmg file. That's because Electron needs to bundle Node and Chromium. I guess that's the cost of convenience. I was looking at other options, for example <a href="https://tauri.app/">Tauri</a> sounded promising, but it comes with fewer out-of-the-box features and, more importantly, it uses the operating system's web view which might lead to inconsistencies across MacOS and Windows. For now I will stick with Electron.</p>

<p>App size aside, Electron is easy to use. The main thing I had to wrap my head around was the main process/renderer process and inter-process communication mechanisms. The main process runs Node and can do things like file I/O and OS-native stuff like setting up the menu bar. The renderer thread runs the app UI. There are several ways for the two processes to exchange data, both synchronously and asynchronously. A good future article I'm planning to write is on commanding: a command like <q>make selection bold</q> cross all layers of the stack, from the editor (which knows whether the current selection is or is not bold), to the DOM, to the main process that handles the menu bar, and back.</p>

<p>As I mentioned above, the app UI is built using React. Most of it is fairly straightforward run-of-the-mill React. The two maybe more interesting bits are the <code>ThemeProvider</code> and the <code>FileProvider</code>. The <code>ThemeProvider</code> handles theming for the app, making sure all windows have the user selected theme applied. The <code>FileProvider</code> helps with IO - it keeps the content of the editor in sync with the file on disk and periodically calls the main process to save the document. Conversely, when the user opens a new file, which happens on the main thread (since the renderer thread can't access the file system), <code>FileProvider</code> ensures the editor loads the new file's content. I will cover the details of this in a future article.</p>

<p><img src="./themes.png" alt="Screenshot"/></p>

<h2>Copilot</h2>

<p>A note on developing with AI: I relied heavily on GitHub Copilot to build this. While I have some prior experience with React, I'm by no means an expert. I never used ProseMirror nor Electron before.</p>

<p>Copilot still has its rough edges. I hit one clear example of incorrect output while working on my Markdown plugin for ProseMirror. It was obvious the model was trained on the ProseMirror code and other projects leveraging the <code>prosemirror-markdown</code> plugin. But since I was using a very different document schema, any code it produced would not be applicable.</p>

<p>A funny observation: I had situations in which OpenAI's model stubbornly repeated its answer even when I was pointing out it is not working. On the other hand, Anthropic's model is very eager to apologize and agree with me (even when I'm in the wrong). Interesting how they each have their own personality.</p>

<p>Complaints aside, before LLMs it would've taking a lot more time and digging through StackOverflow to put something like this together. I definitely feel Copilot makes me much more productive. Even if the code produced is imperfect, it's way easier for me to correct it than to type it up from scratch. Having an LLM I can ask questions is invaluable. I went into this with zero knowledge of ProseMirror and Electron and I know feel a lot more comfortable with both and have a much deeper understanding of how they work.</p>

<h2>End</h2>

<p>In this post I covered the very high-level architecture of Flow. I will follow up with articles that will go deeper on some of the more interesting implementation details. Until then, check out <a href="https://saturn9.studio/flow/">Flow</a>.</p>
]]></description>
      <pubDate>Sat, 08 Mar 2025 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2025/01/01/notes-on-advent-of-code-2024.html</link>
      <guid>https://vladris.com/blog/2025/01/01/notes-on-advent-of-code-2024.html</guid>
      <title><![CDATA[Notes on Advent of Code 2024]]></title>
      <description><![CDATA[<h1>Notes on Advent of Code 2024</h1>

<p>I'm making this a tradition, as I wrote about <a href="https://adventofcode.com/">Advent of
Code</a> during the past couple of years. This is the
10th year of Advent of Code!</p>

<p>All my solutions are on my GitHubÂ <a href="https://github.com/vladris/aoc">here</a>. And
the standard disclaimer:</p>

<blockquote>
<p><strong>Disclaimer on my solutions</strong></p>

<p>I use Python because I find it easiest for this type of coding. I treat
solving these as a write-only exercise. I do it for the problem-solving bit, so
I don't comment the code &amp; once I find the solution I consider itÂ doneÂ - I donât
revisit and try to optimize even though sometimes I strongly feel like there is
a better solution. I don't even share code between part 1 and part 2 - once part
1 is solved, I copy/paste the solution and change it to solve part 2, so each
can be run independently. I also rarely use libraries, and when I do it's some
standard ones likeÂ <code>re</code>,Â <code>itertools</code>, orÂ <code>math</code>. The code has no comments and is
littered with magic numbers and strange variable names. This is not how I
usually code, rather my decadent holiday indulgence. I wasn't thinking I will
end up writing a blog post discussing my solutions so I would like to apologize
for the code being hard to read.</p>
</blockquote>

<p>I won't cover the first few days, as the first problems are always easy. The
first fun one for me this year has been part 2 of Day 12:</p>

<h2>Day 12: Garden Groups</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/12">here</a>.</p>

<p>Part 1 was easy. I used a recursive algorithm like flood-fill to find the area
and perimeter of each garden. Keeping track of the squares already visited, we
add 1 to the area for this square then, if the north, east, south, or west
square has the same letter as the current one, we visit it recursively,
otherwise we add 1 to the perimeter (as we encountered a wall).</p>

<p>Part 2 was more interesting: we need to identify the number of sides rather than
the perimeter. A side is any contiguous boundary that can span multiple squares.
I tried to come up with the simplest way to tell how many sides an area has and
here is what I got: the number of sides is equal to the number of <q>corners</q>, so
rather than counting sides, we can count how many times the the boundary takes a
corner.</p>

<p>For north-west, we have two cases in which we have a corner:</p>
<div class="highlight"><pre><span/>XX   XA
XA   AA
</pre></div>

<p>If our square is <code>A</code>, if both north and sound are <em>not</em> <code>A</code>, we have a corner.
Alternately, if both north and west <em>are</em> <code>A</code> but north west is not, we also
have a corner.</p>

<p>All other permutations have the north east point be part of a segment or within
the area, not a corner:</p>
<div class="highlight"><pre><span/>AA   XA   XX
AA   XA   AA
</pre></div>

<p>With this, we can compute how many of the four points around a square are
corners. Retrofitting this to the part 1 flood-fill algorithm, we can get, for
each area, the total surface and total number of corners.</p>

<h2>Day 13: Claw Contraption</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/13">here</a>.</p>

<p>Part 1 was easy to brute-force, given the <q>at most 100 moves</q> constraint.</p>

<p>Part 2 can't be brute-forced. That said, the solution is very straight-forward:</p>

<p>\[
\left\{
\begin{aligned}
&amp;X_A * i + X_B * j = X_{target} \\
&amp;Y_A * i + Y_B * j = Y_{target}
\end{aligned}
\right.
\]</p>

<p>Here, \(X_A\) and \(Y_A\) are the X and Y offsets we get when pressing button A,
while \(X_B\) and \(Y_B\) are the offsets when pressing button B. Our target
coordinates are at \(X_{target}\) and \(Y_{target}\). So we just need to solve for
\(i\) and \(j\).</p>

<h2>Day 14: Restroom Redoubt</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/14">here</a>.</p>

<p>Part 1 was again easy, just simulate 100 moves for each robot and figure which
quadrant they end up in.</p>

<p>Part 2 was surprising, I was expecting something like instead of 100 moves,
simulate some million moves. I didn't really solve finding the easter egg
algorithmically. Rather I advanced the robots step by step and displayed the
results. I noticed they tend to cluster at certain steps - for my input it was
33, 136, 239 etc. They didn't quite form a picture but I figured I can just look
at steps \(33 + n103\) to find the easter egg, and indeed after a number of
iterations the robots formed a picture!</p>

<h2>Day 15: Warehouse Woes</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/15">here</a>.</p>

<p>Part 1 was very easy.</p>

<p>Part 2 was a bit more tedious. For pushing boxes around horizontally, same code
as part 1 work, but for vertical pushes, we need to account for wider boxes. I
implemented two functions for this, first one just tells us if a move is
possible:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">can_move</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"."</span><span class="p">:</span>
        <span class="k">return</span> <span class="kc">True</span>
    <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"]"</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">can_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span> <span class="ow">and</span> <span class="n">can_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"["</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">can_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span> <span class="ow">and</span> <span class="n">can_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
    <span class="k">return</span> <span class="kc">False</span>
</pre></div>

<p><code>can_move()</code> recurses until it either finds a free <code>.</code> spot for everything that
needs pushing or until it hits a wall, in which case a move is not possible. The
<code>d</code> argument is the direction, since the only difference between going up and
down is whether we subtract 1 or add 1 to the row <code>i</code>.</p>

<p>If a move is possible, then we can update the grid like this:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">do_move</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"."</span><span class="p">:</span>
        <span class="k">return</span>
    <span class="k">elif</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"["</span><span class="p">:</span>
        <span class="n">do_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
        <span class="n">do_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
        <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">][</span><span class="n">j</span><span class="p">],</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">][</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"["</span><span class="p">,</span> <span class="s2">"]"</span>
        <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">],</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"."</span><span class="p">,</span> <span class="s2">"."</span>
    <span class="k">elif</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"]"</span><span class="p">:</span>
        <span class="n">do_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
        <span class="n">do_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
        <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"["</span><span class="p">,</span> <span class="s2">"]"</span>
        <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"."</span><span class="p">,</span> <span class="s2">"."</span>
    <span class="k">elif</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"@"</span><span class="p">:</span>
        <span class="n">do_move</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
        <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="n">d</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"@"</span>
        <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"."</span>
</pre></div>

<p>Not the most pretty but it does the job: if we're on an empty spot <code>.</code>, we stop.
Otherwise if we're on a half of a box, we recursively move up the row above (or
below), then shift the box and replace it with empty space. Only other option is
we're on the <code>@</code>, in which case we also shift it and replace it with empty
space.</p>

<h2>Day 16: Reindeer Maze</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/16">here</a>.</p>

<p>For the first part, I used a queue and kept track at each step of the best score
found so far for the given coordinates + heading. At each step, we can move 1
square towards our heading or rotate 90 degrees, changing our heading. This will
find the best score with which we can reach the destination.</p>
<div class="highlight"><pre><span/><span class="n">s_i</span><span class="p">,</span> <span class="n">s_j</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span>
<span class="n">e_i</span><span class="p">,</span> <span class="n">e_j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">-</span> <span class="mi">2</span>

<span class="n">visited</span><span class="p">,</span> <span class="n">best</span><span class="p">,</span> <span class="n">queue</span> <span class="o">=</span> <span class="p">{},</span> <span class="mi">10</span> <span class="o">**</span> <span class="mi">9</span><span class="p">,</span> <span class="p">[(</span><span class="n">s_i</span><span class="p">,</span> <span class="n">s_j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">,</span> <span class="mi">0</span><span class="p">)]</span>
<span class="k">while</span> <span class="n">queue</span><span class="p">:</span>
    <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">heading</span><span class="p">,</span> <span class="n">score</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">==</span> <span class="s2">"#"</span><span class="p">:</span>
        <span class="k">continue</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">heading</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">heading</span><span class="p">)]</span> <span class="o">&lt;=</span> <span class="n">score</span><span class="p">:</span>
        <span class="k">continue</span>

    <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">heading</span><span class="p">)]</span> <span class="o">=</span> <span class="n">score</span>

    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="n">e_i</span> <span class="ow">and</span> <span class="n">j</span> <span class="o">==</span> <span class="n">e_j</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">score</span> <span class="o">&lt;</span> <span class="n">best</span><span class="p">:</span>
            <span class="n">best</span> <span class="o">=</span> <span class="n">score</span>
        <span class="k">continue</span>

    <span class="k">match</span> <span class="n">heading</span><span class="p">:</span>
        <span class="k">case</span> <span class="s2">"E"</span><span class="p">:</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1000</span><span class="p">))</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1000</span><span class="p">))</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">heading</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
        <span class="k">case</span> <span class="s2">"N"</span><span class="p">:</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1000</span><span class="p">))</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1000</span><span class="p">))</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">heading</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
        <span class="k">case</span> <span class="s2">"W"</span><span class="p">:</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1000</span><span class="p">))</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1000</span><span class="p">))</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">heading</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
        <span class="k">case</span> <span class="s2">"S"</span><span class="p">:</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1000</span><span class="p">))</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1000</span><span class="p">))</span>
            <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">heading</span><span class="p">,</span> <span class="n">score</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
</pre></div>

<p>For part 2, my solution ended up quite long. I didn't want to update change the
traversal algorithm from part 1. Rather, I figured we can re-construct the best
paths starting from the end and looking at the visited squares we've been
keeping track of: if, for example, we are at coordinates <code>i</code>, <code>j</code>, and heading
<code>"N"</code> (north) with a score of <code>S</code>, then if the score we have for <code>(i - 1, j,
"N")</code> is <code>S - 1</code>, then the square at <code>i - 1</code>, <code>j</code> (with heading <code>N</code>) is also
part of the best path. Similarly, if <code>(i, j, "E")</code> or <code>(i, j "W")</code> had score <code>S
- 1000</code>, then turning is also part of the best path.</p>

<p>We already have all the scores in <code>visted</code>, so I reconstructed the best paths by
backtracking from the end:</p>
<div class="highlight"><pre><span/><span class="n">path</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">def</span><span class="w"> </span><span class="nf">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">heading</span><span class="p">,</span> <span class="n">score</span><span class="p">):</span>
    <span class="n">path</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">))</span>
    
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="n">s_i</span> <span class="ow">and</span> <span class="n">j</span> <span class="o">==</span> <span class="n">s_j</span> <span class="ow">and</span> <span class="n">heading</span> <span class="o">==</span> <span class="s2">"E"</span> <span class="ow">and</span> <span class="n">score</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span>
    
    <span class="k">match</span> <span class="n">heading</span><span class="p">:</span>
        <span class="k">case</span> <span class="s2">"E"</span><span class="p">:</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">case</span> <span class="s2">"N"</span><span class="p">:</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">case</span> <span class="s2">"W"</span><span class="p">:</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"N"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">case</span> <span class="s2">"S"</span><span class="p">:</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"W"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"E"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1000</span><span class="p">)</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span> <span class="ow">and</span> <span class="n">visited</span><span class="p">[(</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">)]</span> <span class="o">==</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
                <span class="n">backtrack</span><span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="s2">"S"</span><span class="p">,</span> <span class="n">score</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>


<span class="n">backtrack</span><span class="p">(</span><span class="n">e_i</span><span class="p">,</span> <span class="n">e_j</span><span class="p">,</span> <span class="n">best</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">best</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
</pre></div>

<p>This is not the prettiest implementation but after running this, the length of
<code>path</code> gives us the solution. Some of this can be condensed: if we're heading
either <code>"E"</code> or <code>"W"</code>, we can only change heading to <code>"N"</code> or <code>"S"</code> etc., but
GitHub Copilot was very good at filling in all the different cases, so I just
went with it.</p>

<h2>Day 17: Chronospatial Computer</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/17">here</a>.</p>

<p>The first part was easy, just simulate the machine and execute the instructions.</p>

<p>The second part was a lot more fun. It was clear it's too hard to brute-force,
so I had to spend some time analyzing the program itself. For my input, it
looked like this:</p>
<div class="highlight"><pre><span/>bst @A
bxl 1
cdv @B
bxc
bxl 4
adv 3
out @B
jnz 0
</pre></div>

<p>In other words:</p>
<div class="highlight"><pre><span/>B &lt;- A % 8 (last 3 bits of A)
B &lt;- B XOR 1
C &lt;- A &gt;&gt; B
B &lt;- B XOR C
B &lt;- B XOR 4
A &lt;- A &gt;&gt; 3 (right-shift A 3 bits)
OUT &lt;- B % 8 (last 3 bits of B)
JNZ 0 (repeat until A is 0)
</pre></div>

<p>The key takeaways from this are:</p>

<ul>
<li>Each step consumes the last 3 bits of register A</li>
<li>...which means B is between 0 and 7</li>
<li>...which C is A right-shifted by at most 7 bits</li>
<li>...then B gets XORed with 4 and C</li>
<li>...and we print its last 3 bits</li>
</ul>

<p>At most the last 10 bits of A are relevant to producing an output (since C is A
right-shifted by at most 7 bits and XORed with B which comes out of the last 3
bits of A).</p>

<p>I implemented a function that takes a value of register A and prints the output
after one iteration:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">step</span><span class="p">(</span><span class="n">a</span><span class="p">):</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">a</span> <span class="o">%</span> <span class="mi">8</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">b</span> <span class="o">^</span> <span class="mi">1</span>
    <span class="n">c</span> <span class="o">=</span> <span class="n">a</span> <span class="o">//</span> <span class="mi">2</span> <span class="o">**</span> <span class="n">b</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">b</span> <span class="o">^</span> <span class="n">c</span>
    <span class="n">b</span> <span class="o">=</span> <span class="n">b</span> <span class="o">^</span> <span class="mi">4</span>
    <span class="k">return</span> <span class="n">b</span> <span class="o">%</span> <span class="mi">8</span>
</pre></div>

<p>We search for the solution in groups of 3 bits:</p>

<ul>
<li>We find all permutations of 10 bits that produce the output number we want</li>
<li>We prepend the last 3 bits to our solution</li>
<li>We recursively look for the values that produce the next 3 bits but we keep
the remaining 7 bits from this step as a suffix we expect the next iteration
to have</li>
</ul>

<p>So if we find that, say <code>b1000101010</code> outputs the first number we want, <code>4</code>, we
store the last 3 bits (<code>010</code>) as part of our solution but also expect numbers at
the next step to end with <code>1000101</code>.</p>

<p>Once we find all numbers in the program this way, we make sure the suffix is 0
(we shouldn't be expecting more digits as we should terminate the program), and
we found a solution. We can keep track of which of the solutions we found is the
smallest one. The whole search function is here:</p>
<div class="highlight"><pre><span/><span class="n">best</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">**</span> <span class="mi">20</span>
<span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="n">i</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">valid_suffix</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">best</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">prog</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">valid_suffix</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">best</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">best</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
        <span class="k">return</span>

    <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1024</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">valid_suffix</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">x</span> <span class="o">&amp;</span> <span class="p">(</span><span class="mi">2</span> <span class="o">**</span> <span class="mi">7</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">!=</span> <span class="n">valid_suffix</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="k">if</span> <span class="n">step</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">==</span> <span class="n">prog</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
            <span class="n">search</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">x</span> <span class="o">&gt;&gt;</span> <span class="mi">3</span><span class="p">,</span> <span class="p">((</span><span class="n">x</span> <span class="o">%</span> <span class="mi">8</span><span class="p">)</span> <span class="o">&lt;&lt;</span> <span class="p">(</span><span class="mi">3</span> <span class="o">*</span> <span class="n">i</span><span class="p">))</span> <span class="o">+</span> <span class="n">n</span><span class="p">)</span>
</pre></div>

<p><code>prog</code> contains the program instructions - the numbers we are searching for. If
we found all of them, <code>valid_suffix</code> should be 0, otherwise we don't have a
solution as our program will continue running and producing more output. We
convert <code>n</code> from a binary string to a number, and store the minimum we found so
far in <code>best</code>.</p>

<p>Otherwise we produce all permutations of 10 bits, which means counting to 1024.
If we have a <code>valid_suffix</code> we need to respect, we filter out values that don't
match the suffix. Next, we check if running a step of the program on these 10
bits produces the number we want. If so, we found the next 3 bits of our
solution, we recurse, looking for the next number (<code>i + 1</code>), setting the most
significant 7 bits of x as the expected suffix (<code>x &gt;&gt; 3</code>), then we prepend the
last 3 bits of x to the number we found so far (the math there just makes sure
we prepend it to <code>n</code>: <code>((x % 8) &lt;&lt; (3 * i)) + n</code> shifts the last 3 digits we
found enough to go in front of <code>n</code>).</p>

<p>This problem was fun, as I had to reverse-engineer the program to figure out an
efficient way to search for the solution.</p>

<h2>Day 18: RAM Run</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/18">here</a>.</p>

<p>This one was easy. The first part is another maze traversal, very much like day
16.</p>

<p>The second part is also easy: we keep adding bytes to the memory one by one and
check that the exit is still reachable. At some point, it stops being reachable
and we found our solution. As long as traversal is efficient, it's no problem
running it multiple times. Unlike part 1, we don't even need to find the
shortest path, just whether the exit can be reached or not.</p>

<h2>Day 19: Linen Layout</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/19">here</a>.</p>

<p>Another surprisingly easy one. For part 1, the only gotcha is the input has much
larger sequences than the example, so trying all permutations would take a long
time unless we use memoization. Once we match a pattern suffix, we keep track of
whether we matched it or not. With this, the solution is just a few lines of
code:</p>
<div class="highlight"><pre><span/><span class="n">matched</span> <span class="o">=</span> <span class="p">{</span><span class="s2">""</span><span class="p">:</span> <span class="kc">True</span><span class="p">}</span>

<span class="k">def</span><span class="w"> </span><span class="nf">match</span><span class="p">(</span><span class="n">pattern</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">pattern</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">matched</span><span class="p">:</span>
        <span class="n">matched</span><span class="p">[</span><span class="n">pattern</span><span class="p">]</span> <span class="o">=</span> <span class="nb">any</span><span class="p">(</span><span class="n">match</span><span class="p">(</span><span class="n">pattern</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">towel</span><span class="p">):])</span> <span class="k">for</span> <span class="n">towel</span> <span class="ow">in</span> <span class="n">towels</span> <span class="k">if</span> <span class="n">pattern</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">towel</span><span class="p">))</span>

    <span class="k">return</span> <span class="n">matched</span><span class="p">[</span><span class="n">pattern</span><span class="p">]</span>


<span class="nb">print</span><span class="p">(</span><span class="nb">sum</span><span class="p">(</span><span class="n">match</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> <span class="k">for</span> <span class="n">pattern</span> <span class="ow">in</span> <span class="n">patterns</span><span class="p">))</span>
</pre></div>

<p>Here, <code>towels</code> is the list of available towels, and <code>patterns</code> is the list of
patterns to produce.</p>

<p>Part 2 asks us to count all possible combinations that produce a pattern rather
than just whether we can or cannot produce it. We can get this with minimal
modifications to the part 1 solution: we consider matching <code>""</code> to be <code>1</code>, and
instead of <code>any()</code>, we use <code>sum()</code> in the recursive function:</p>
<div class="highlight"><pre><span/><span class="n">matched</span> <span class="o">=</span> <span class="p">{</span><span class="s2">""</span><span class="p">:</span> <span class="mi">1</span><span class="p">}</span>

<span class="k">def</span><span class="w"> </span><span class="nf">match</span><span class="p">(</span><span class="n">pattern</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">pattern</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">matched</span><span class="p">:</span>
        <span class="n">matched</span><span class="p">[</span><span class="n">pattern</span><span class="p">]</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">match</span><span class="p">(</span><span class="n">pattern</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">towel</span><span class="p">):])</span> <span class="k">for</span> <span class="n">towel</span> <span class="ow">in</span> <span class="n">towels</span> <span class="k">if</span> <span class="n">pattern</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">towel</span><span class="p">))</span>

    <span class="k">return</span> <span class="n">matched</span><span class="p">[</span><span class="n">pattern</span><span class="p">]</span>


<span class="nb">print</span><span class="p">(</span><span class="nb">sum</span><span class="p">(</span><span class="n">match</span><span class="p">(</span><span class="n">pattern</span><span class="p">)</span> <span class="k">for</span> <span class="n">pattern</span> <span class="ow">in</span> <span class="n">patterns</span><span class="p">))</span>
</pre></div>

<p>This counts all possible combinations.</p>

<h2>Day 20: Race Condition</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/20">here</a>.</p>

<p>This was another surprisingly easy one. Since there is a single path through the
maze without cheating, my approach was to first determine how far away each
point that is not a wall is from the exit:</p>
<div class="highlight"><pre><span/><span class="n">dist</span><span class="p">,</span> <span class="n">at</span> <span class="o">=</span> <span class="p">{</span><span class="n">end</span><span class="p">:</span> <span class="mi">0</span><span class="p">},</span> <span class="n">end</span>
<span class="k">while</span> <span class="n">at</span> <span class="o">!=</span> <span class="n">start</span><span class="p">:</span>
    <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">at</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">dist</span> <span class="ow">and</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"#"</span><span class="p">:</span>
        <span class="n">dist</span><span class="p">[(</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">)]</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[</span><span class="n">at</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="n">at</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span>
    <span class="k">elif</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">dist</span> <span class="ow">and</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"#"</span><span class="p">:</span>
        <span class="n">dist</span><span class="p">[(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">)]</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[</span><span class="n">at</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="n">at</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span>
    <span class="k">elif</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">dist</span> <span class="ow">and</span> <span class="n">grid</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"#"</span><span class="p">:</span>
        <span class="n">dist</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)]</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[</span><span class="n">at</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="n">at</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">dist</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[</span><span class="n">at</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="n">at</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>

<p>Traversal is easy: starting from the exit point, there should always be a single
not visited space we can go to next. Once we have this, the solution is easy.
For each <code>(i, j)</code> we can be on, meaning the keys of <code>dist</code>, we check if <code>(i - 2,
j)</code>, <code>(i, j - 2)</code> etc. are in <code>dist</code> too (so all places we can get to in two
steps, ignoring walls). If any of the new coordinates are also in <code>dist</code>, we
check if we have indeed a shortcut: <code>dist[(i, j)] - dist[(i + dx, j + dy]) -
2 &gt;= 100</code>. That is, the distance at <code>(i, j)</code> minus the distance at the end of
the cheat <code>(i + dx, j + dy)</code> minus <code>2</code> for the two steps we take while cheating
is greater than 100. Here, <code>(dx, dy)</code> is any of <code>[(-2, 0), (0, -2), (2, 0), (0,
2), (-1, -1), (-1, 1), (1, -1), (1, 1)]</code>.  Counting these gives us all the
cheats:</p>
<div class="highlight"><pre><span/><span class="n">shortcuts</span> <span class="o">=</span> <span class="mi">0</span>

<span class="k">def</span><span class="w"> </span><span class="nf">cheat</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">dx</span><span class="p">,</span> <span class="n">dy</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">shortcuts</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="n">dx</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="n">dy</span><span class="p">)</span> <span class="ow">in</span> <span class="n">dist</span> <span class="ow">and</span> <span class="n">dist</span><span class="p">[(</span><span class="n">i</span> <span class="o">+</span> <span class="n">dx</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="n">dy</span><span class="p">)]</span> <span class="o">&lt;</span> <span class="n">dist</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)]</span> <span class="o">-</span> <span class="mi">2</span><span class="p">:</span>
        <span class="n">d</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)]</span> <span class="o">-</span> <span class="n">dist</span><span class="p">[(</span><span class="n">i</span> <span class="o">+</span> <span class="n">dx</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="n">dy</span><span class="p">)]</span> <span class="o">-</span> <span class="mi">2</span>
        <span class="k">if</span> <span class="n">d</span> <span class="o">&gt;=</span> <span class="mi">100</span><span class="p">:</span>
            <span class="n">shortcuts</span> <span class="o">+=</span> <span class="mi">1</span>


<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">:</span>
    <span class="k">for</span> <span class="p">(</span><span class="n">dx</span><span class="p">,</span> <span class="n">dy</span><span class="p">)</span> <span class="ow">in</span> <span class="p">[(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]:</span>
        <span class="n">cheat</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">dx</span><span class="p">,</span> <span class="n">dy</span><span class="p">)</span>
</pre></div>

<p>Part 2 is not much more difficult. We can now cheat for up to 20 steps rather
than just 2. That means instead of the hardcoded list of <code>(dx, dy)</code> we
considered at step 1, we instead need to look for all coordinates <code>(si, sj)</code>
that are also in <code>dist</code>, with a Manhattan distance of at most 20 from <code>(i, j)</code>.
I implemented a function that gives us all the candidates:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">candidates</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">si</span><span class="p">,</span> <span class="n">sj</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">si</span> <span class="o">==</span> <span class="n">i</span> <span class="ow">and</span> <span class="n">sj</span> <span class="o">==</span> <span class="n">j</span><span class="p">:</span>
            <span class="k">continue</span>
        <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">si</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sj</span> <span class="o">-</span> <span class="n">j</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="mi">20</span><span class="p">:</span>
            <span class="k">yield</span> <span class="n">si</span><span class="p">,</span> <span class="n">sj</span>
</pre></div>

<p>With this, we can update the algorithm from part 1 as follows:</p>
<div class="highlight"><pre><span/><span class="n">shortcuts</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">si</span><span class="p">,</span> <span class="n">sj</span> <span class="ow">in</span> <span class="n">candidates</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">):</span>
        <span class="n">d</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[(</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)]</span> <span class="o">-</span> <span class="n">dist</span><span class="p">[(</span><span class="n">si</span><span class="p">,</span> <span class="n">sj</span><span class="p">)]</span> <span class="o">-</span> <span class="p">(</span><span class="nb">abs</span><span class="p">(</span><span class="n">si</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sj</span> <span class="o">-</span> <span class="n">j</span><span class="p">))</span>
        <span class="k">if</span> <span class="n">d</span> <span class="o">&gt;=</span> <span class="mi">100</span><span class="p">:</span>
            <span class="n">shortcuts</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>

<p>This will gives us all the cheats for part 2.</p>

<h2>Day 21: Keypad Conundrum</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/21">here</a>.</p>

<p>This was a bit tedious, but fun. It was the first one this year that took me a
bit longer to solve. I solved this bottom-up, so there might be a more concise
solution, but this is what I got: for part 1, I first represented the two types
of keypads as graphs:</p>
<div class="highlight"><pre><span/><span class="n">num_pad</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s2">"A"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"0"</span><span class="p">,</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"3"</span> <span class="p">},</span>
    <span class="s2">"0"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"A"</span><span class="p">,</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"2"</span> <span class="p">},</span>
    <span class="s2">"1"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"4"</span><span class="p">,</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"2"</span><span class="p">},</span>
    <span class="s2">"2"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"1"</span><span class="p">,</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"5"</span><span class="p">,</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"3"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"0"</span> <span class="p">},</span>
    <span class="s2">"3"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"2"</span><span class="p">,</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"6"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"A"</span> <span class="p">},</span>
    <span class="s2">"4"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"7"</span><span class="p">,</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"5"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"1"</span> <span class="p">},</span>
    <span class="s2">"5"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"4"</span><span class="p">,</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"8"</span><span class="p">,</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"6"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"2"</span> <span class="p">},</span>
    <span class="s2">"6"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"5"</span><span class="p">,</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"9"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"3"</span> <span class="p">},</span>
    <span class="s2">"7"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"8"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"4"</span> <span class="p">},</span>
    <span class="s2">"8"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"7"</span><span class="p">,</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"9"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"5"</span> <span class="p">},</span>
    <span class="s2">"9"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"8"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"6"</span> <span class="p">},</span>
<span class="p">}</span>

<span class="n">dir_pad</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s2">"^"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"A"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"v"</span> <span class="p">},</span>
    <span class="s2">"A"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"^"</span><span class="p">,</span> <span class="s2">"v"</span><span class="p">:</span> <span class="s2">"&gt;"</span> <span class="p">},</span>
    <span class="s2">"&lt;"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"v"</span> <span class="p">},</span>
    <span class="s2">"v"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"&lt;"</span><span class="p">,</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"^"</span><span class="p">,</span> <span class="s2">"&gt;"</span><span class="p">:</span> <span class="s2">"&gt;"</span> <span class="p">},</span>
    <span class="s2">"&gt;"</span><span class="p">:</span> <span class="p">{</span> <span class="s2">"&lt;"</span><span class="p">:</span> <span class="s2">"v"</span><span class="p">,</span> <span class="s2">"^"</span><span class="p">:</span> <span class="s2">"A"</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Note I used an <em>edge-to-node</em> representation. Then I wrote a function to
computed all possible paths in a given graph between two nodes:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">paths</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="n">dest</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="n">graph</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="n">dest</span><span class="p">:</span>
        <span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="o">+</span> <span class="s2">"A"</span><span class="p">)</span>
        <span class="k">return</span>

    <span class="n">visited</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">direction</span><span class="p">,</span> <span class="n">next_i</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
        <span class="k">if</span> <span class="n">next_i</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="k">continue</span>
        
        <span class="n">visited</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">next_i</span><span class="p">)</span>
        <span class="n">path</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">direction</span><span class="p">)</span>
        
        <span class="n">paths</span><span class="p">(</span><span class="n">next_i</span><span class="p">,</span> <span class="n">dest</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="n">graph</span><span class="p">,</span> <span class="n">visited</span><span class="p">,</span> <span class="n">path</span><span class="p">)</span>
        
        <span class="n">visited</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">next_i</span><span class="p">)</span>
        <span class="n">path</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
</pre></div>

<p>The result is accumulated in the <code>result</code> parameter. With this, I generated all
possible paths between any two nodes in both graphs:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">map_path</span><span class="p">(</span><span class="n">graph</span><span class="p">):</span>
    <span class="n">path_map</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="k">for</span> <span class="n">k1</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">k2</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">k1</span> <span class="o">==</span> <span class="n">k2</span><span class="p">:</span>
                <span class="n">path_map</span><span class="p">[(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">)]</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"A"</span><span class="p">]</span>
                <span class="k">continue</span>

            <span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
            <span class="n">paths</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="n">graph</span><span class="p">,</span> <span class="nb">set</span><span class="p">(),</span> <span class="p">[])</span>
            <span class="n">path_map</span><span class="p">[(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">)]</span> <span class="o">=</span> <span class="n">result</span>
    <span class="k">return</span> <span class="n">path_map</span>


<span class="n">num_pad_moves</span> <span class="o">=</span> <span class="n">map_path</span><span class="p">(</span><span class="n">num_pad</span><span class="p">)</span>
<span class="n">dir_pad_moves</span> <span class="o">=</span> <span class="n">map_path</span><span class="p">(</span><span class="n">dir_pad</span><span class="p">)</span>
</pre></div>

<p>The <code>map_path()</code> function generates all possible paths between any combination
of nodes. I stored the results in <code>num_pad_moves</code> and <code>dir_path_moves</code> for the
number pad and the directions pad.</p>

<p>The main gotcha of this problem is we can't brute force all possible
combinations of, say, going from <code>9</code> to <code>0</code> on the number pad, as each level
has, in turn, different ways to produce a working combination. This blows up
fast.</p>

<p>Also, the shortest path at one level might not be the shortest one at the next
level. For example, a path like <code>&lt;&lt;&lt;</code> at the higher level pad translates into
navigating the lower level to <code>&lt;</code> then pressing <code>A</code> 3 times. If the lower level
keys are further apart, the higher level requires more presses to get there, so
we also can't just look at the shortest path at the lower level to figure out
the best solution for the higher level.</p>

<p>On the other hand, I realized that once we do know at the next higher level how
to best get the lower level from one key to another, we don't need to recompute
that. So if, say, the second robot needs to get from <code>&lt;</code> to <code>&gt;</code>, the robot one
level above can always use the same optimal combination of key presses to get it
to do so. The search space for this is actually quite small. So I started with
the highest level, the best combinations of keys I can press to get the robot
one level below to go from any key to any other key:</p>
<div class="highlight"><pre><span/><span class="n">best_moves</span> <span class="o">=</span> <span class="p">{</span>
    <span class="mi">1</span><span class="p">:</span> <span class="p">{</span> <span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">):</span> <span class="nb">min</span><span class="p">(</span><span class="n">dir_pad_moves</span><span class="p">[(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">)],</span> <span class="n">key</span><span class="o">=</span><span class="nb">len</span><span class="p">)</span> <span class="k">for</span> <span class="n">k1</span><span class="p">,</span> <span class="n">k2</span> <span class="ow">in</span> <span class="n">dir_pad_moves</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>These are the best moves for level 1, the robot right below. Then I implemented
a function which, given a pair of nodes and a depth level, returns the best
(shortest) combination of keys:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">sequence</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">,</span> <span class="n">depth</span><span class="p">,</span> <span class="n">graph</span><span class="o">=</span><span class="n">dir_pad_moves</span><span class="p">):</span>
    <span class="n">best</span><span class="p">,</span> <span class="n">best_len</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="mi">10</span> <span class="o">**</span> <span class="mi">10</span>
    <span class="k">for</span> <span class="n">path</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">)]:</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">k</span> <span class="o">:=</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">best_moves</span><span class="p">[</span><span class="n">depth</span><span class="p">][</span><span class="n">p</span><span class="p">]</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="s2">"A"</span> <span class="o">+</span> <span class="n">path</span><span class="p">,</span> <span class="n">path</span><span class="p">)))</span> <span class="o">&lt;</span> <span class="n">best_len</span><span class="p">:</span>
            <span class="n">best</span><span class="p">,</span> <span class="n">best_len</span> <span class="o">=</span> <span class="n">k</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">best</span>
</pre></div>

<p>For each path we can take between nodes <code>k1</code> and <code>k2</code> in our graph, we look at
what is the concatenation of the best moves we can take at that level. We return
the shortest result. I'm prepending an <code>"A"</code> to the path here, as we always
start from atop the <code>"A"</code> key on any keypad.</p>

<p>Now we can use the <code>best_moves</code> for level 1 to populate the best moves for level
2, then do level 3 the same way:</p>
<div class="highlight"><pre><span/><span class="n">best_moves</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">{(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">):</span> <span class="n">sequence</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">dir_pad_moves</span><span class="p">)</span> <span class="k">for</span> <span class="n">k1</span><span class="p">,</span> <span class="n">k2</span> <span class="ow">in</span> <span class="n">dir_pad_moves</span><span class="p">}</span>
<span class="n">best_moves</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">{(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">):</span> <span class="n">sequence</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="n">num_pad_moves</span><span class="p">)</span> <span class="k">for</span> <span class="n">k1</span><span class="p">,</span> <span class="n">k2</span> <span class="ow">in</span> <span class="n">num_pad_moves</span><span class="p">}</span>
</pre></div>

<p>Now <code>best_moves[3]</code> contains the shortest path (in terms of key presses at the
highest level) to go between any two keys. We can easily produce the value we
need from there:</p>
<div class="highlight"><pre><span/><span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">code</span> <span class="ow">in</span> <span class="n">codes</span><span class="p">:</span>
    <span class="n">result</span> <span class="o">=</span> <span class="s2">""</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">best_moves</span><span class="p">[</span><span class="mi">3</span><span class="p">][</span><span class="n">pair</span><span class="p">]</span> <span class="k">for</span> <span class="n">pair</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="s2">"A"</span> <span class="o">+</span> <span class="n">code</span><span class="p">,</span> <span class="n">code</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="o">*</span> <span class="nb">int</span><span class="p">(</span><span class="n">code</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</pre></div>

<p>For part 2, I first thought of simply scaling out the solution to part 1 -
instead of computing <code>best_moves</code> 3 levels deep, do it 26 levels deep. This
should theoretically work, but it blows up the memory because we're dealing with
larger and larger sequences of keypresses. I realized we don't actually care
about the strings themselves, rather we just need the lengths for our result.</p>

<p>I modified the part 1 code to just look at lengths. <code>best_moves</code> is now
initialized with the minimum path length rather than just the path:</p>
<div class="highlight"><pre><span/><span class="n">best_moves</span> <span class="o">=</span> <span class="p">{</span>
    <span class="mi">1</span><span class="p">:</span> <span class="p">{</span> <span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">):</span> <span class="nb">len</span><span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">dir_pad_moves</span><span class="p">[(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">)],</span> <span class="n">key</span><span class="o">=</span><span class="nb">len</span><span class="p">))</span> <span class="k">for</span> <span class="n">k1</span><span class="p">,</span> <span class="n">k2</span> <span class="ow">in</span> <span class="n">dir_pad_moves</span> <span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>sequence()</code> now assumes <code>best_moves</code> contains lengths and returns a length
itself:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">sequence</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">,</span> <span class="n">depth</span><span class="p">,</span> <span class="n">graph</span><span class="o">=</span><span class="n">dir_pad_moves</span><span class="p">):</span>
    <span class="n">best</span> <span class="o">=</span> <span class="mi">10</span> <span class="o">**</span> <span class="mi">20</span>
    <span class="k">for</span> <span class="n">path</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">)]:</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">k</span> <span class="o">:=</span> <span class="nb">sum</span><span class="p">(</span><span class="n">best_moves</span><span class="p">[</span><span class="n">depth</span><span class="p">][</span><span class="n">p</span><span class="p">]</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="s2">"A"</span> <span class="o">+</span> <span class="n">path</span><span class="p">,</span> <span class="n">path</span><span class="p">)))</span> <span class="o">&lt;</span> <span class="n">best</span><span class="p">:</span>
            <span class="n">best</span> <span class="o">=</span> <span class="n">k</span>
    <span class="k">return</span> <span class="n">best</span>
</pre></div>

<p>Now we can scale out building <code>best_moves</code> up to 26 levels:</p>
<div class="highlight"><pre><span/><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">26</span><span class="p">):</span>
    <span class="n">best_moves</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">{(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">):</span> <span class="n">sequence</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">,</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">dir_pad_moves</span><span class="p">)</span> <span class="k">for</span> <span class="n">k1</span><span class="p">,</span> <span class="n">k2</span> <span class="ow">in</span> <span class="n">dir_pad_moves</span><span class="p">}</span>
<span class="n">best_moves</span><span class="p">[</span><span class="mi">26</span><span class="p">]</span> <span class="o">=</span> <span class="p">{(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">):</span> <span class="n">sequence</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">k2</span><span class="p">,</span> <span class="mi">25</span><span class="p">,</span> <span class="n">num_pad_moves</span><span class="p">)</span> <span class="k">for</span> <span class="n">k1</span><span class="p">,</span> <span class="n">k2</span> <span class="ow">in</span> <span class="n">num_pad_moves</span><span class="p">}</span>
</pre></div>

<p>With this, we can get the solution the same way we did in part 1. Note the same
solution would've worked for part 1. Strings are not needed at all, it just took
me until part 2 to realize this.</p>

<p>This was a neat problem. The part I found tedious was generating the keypad
graphs and computing the possible paths between nodes. But outside of that, I
really enjoyed it. Both parts had an <q>aha</q> moment for me, which is my favorite
part of Advent of Code and puzzles in general.</p>

<h2>Day 22: Monkey Market</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/22">here</a>.</p>

<p>This one was very easy, as I was able to brute force the solution for both part
1 and part 2. For part 1, with the set up of multiplying, XORing, and modulo, I
was thinking I'll have to derive some formula to speed up computation, but that
wasn't the case. I got the results reasonably fast without having to do anything
clever. I implemented this function to advance a number one step:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">step</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">n</span> <span class="o">=</span> <span class="p">((</span><span class="n">n</span> <span class="o">*</span> <span class="mi">64</span><span class="p">)</span> <span class="o">^</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16777216</span>
    <span class="n">n</span> <span class="o">=</span> <span class="p">((</span><span class="n">n</span> <span class="o">//</span> <span class="mi">32</span><span class="p">)</span> <span class="o">^</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16777216</span>
    <span class="n">n</span> <span class="o">=</span> <span class="p">((</span><span class="n">n</span> <span class="o">*</span> <span class="mi">2048</span><span class="p">)</span> <span class="o">^</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16777216</span>
    <span class="k">return</span> <span class="n">n</span>
</pre></div>

<p>Then getting the result was straightforward:</p>
<div class="highlight"><pre><span/><span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">nums</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2000</span><span class="p">):</span>
        <span class="n">n</span> <span class="o">=</span> <span class="n">step</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">n</span>
</pre></div>

<p>I was expecting part 2 will maybe introduce larger numbers (like instead of 2000
iterations, do 2000000) but no. I have a solution that runs in under 1 minute
and gets the correct result. First, I updated the step function to also return
the change in the least significant digit between the old value and the new
value, plus 9 (more on the plus 9 below):</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">step</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">d</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span>
    <span class="n">n</span> <span class="o">=</span> <span class="p">((</span><span class="n">n</span> <span class="o">*</span> <span class="mi">64</span><span class="p">)</span> <span class="o">^</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16777216</span>
    <span class="n">n</span> <span class="o">=</span> <span class="p">((</span><span class="n">n</span> <span class="o">//</span> <span class="mi">32</span><span class="p">)</span> <span class="o">^</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16777216</span>
    <span class="n">n</span> <span class="o">=</span> <span class="p">((</span><span class="n">n</span> <span class="o">*</span> <span class="mi">2048</span><span class="p">)</span> <span class="o">^</span> <span class="n">n</span><span class="p">)</span> <span class="o">%</span> <span class="mi">16777216</span>
    <span class="k">return</span> <span class="n">n</span><span class="p">,</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">-</span> <span class="n">d</span> <span class="o">+</span> <span class="mi">9</span>
</pre></div>

<p>Then, for each initial number, I generate the next 2000 numbers, track the
sequence given by the 4 changes, and the value we would get if the monkey would
buy this sequence for this number:</p>
<div class="highlight"><pre><span/><span class="n">buys</span><span class="p">,</span> <span class="n">seq</span> <span class="o">=</span> <span class="p">{},</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">nums</span><span class="p">):</span>
    <span class="n">buys</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">{}</span>
    <span class="n">n</span><span class="p">,</span> <span class="n">d1</span> <span class="o">=</span> <span class="n">step</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
    <span class="n">n</span><span class="p">,</span> <span class="n">d2</span> <span class="o">=</span> <span class="n">step</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
    <span class="n">n</span><span class="p">,</span> <span class="n">d3</span> <span class="o">=</span> <span class="n">step</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
    <span class="n">change</span> <span class="o">=</span> <span class="n">d1</span> <span class="o">*</span> <span class="mi">19</span> <span class="o">**</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">d2</span> <span class="o">*</span> <span class="mi">19</span> <span class="o">+</span> <span class="n">d3</span>
    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1997</span><span class="p">):</span>
        <span class="n">n</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="n">step</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
        <span class="n">change</span> <span class="o">=</span> <span class="p">(</span><span class="n">change</span> <span class="o">%</span> <span class="mi">19</span> <span class="o">**</span> <span class="mi">3</span><span class="p">)</span> <span class="o">*</span> <span class="mi">19</span> <span class="o">+</span> <span class="n">d</span>
        <span class="n">seq</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">change</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">change</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">buys</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
            <span class="n">buys</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">change</span><span class="p">]</span> <span class="o">=</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">10</span>
</pre></div>

<p>Since the first 3 numbers don't have a sequence (we need 4 changes), I hoisted
these out of the loop. That's the first 3 calls to <code>step()</code>. The change between
2 numbers can be any value between -9 and 9. If the previous digit is 9 and the
current one is 0, the change is -9. If the previous digit is 0 and the current
one is 9, the change is 9. Instead of keeping track of 4 different numbers, we
can encode the sequence into a single number. There are 18 possible values
between -9 and 9, so if we add 9, we get a number between 0 and 18. This way, we
can uniquely encode 4 digits as \(d_1 * 19^3 + d_2 * 19^2 + d_3 * 19 + d_4\).</p>

<p>I'm storing this in <code>change</code>. At each step, we get rid of the oldest change by
getting the modulo \(19^3\) of the value, then we multiply by 19 and add the new
change. If we haven't seen <code>change</code> before for this buyer, we store the last
digit of <code>n</code> in <code>buys[i][change]</code> where <code>i</code> is the index of the buyer, <code>change</code>
is the sequence.</p>

<p>After executing this, <code>buys</code> will contain all possible values for all possible
sequences for each buyer. As a small optimization trading off memory for speed,
I'm also storing all sequences we've seen in the <code>seq</code> set.</p>

<p>To produce the result, we can simply try each sequence from <code>seq</code> and add up the
values we get for each buyer:</p>
<div class="highlight"><pre><span/><span class="n">best</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">seq</span><span class="p">:</span>
    <span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">nums</span><span class="p">)):</span>
        <span class="k">if</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">buys</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
            <span class="n">total</span> <span class="o">+=</span> <span class="n">buys</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">s</span><span class="p">]</span>
    <span class="n">best</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">total</span><span class="p">,</span> <span class="n">best</span><span class="p">)</span>
</pre></div>

<p>Without the optimization, we can simply try all possible sequences, which is up
to \(19^4\).  It's a large number (130321), but not astronomical. With the
optimization, for my input, we only need to try 40951 values.</p>

<p>As I said, this solves the problem in less than a minute. There's probably a
smarter, faster solution, but brute force was good enough here.</p>

<h2>Day 23: LAN Party</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/23">here</a>.</p>

<p>This one was easy. For both parts 1 and 2, I represented the connections as an
undirected graph. Starting with the connected pairs:</p>
<div class="highlight"><pre><span/><span class="n">graph</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">pair</span> <span class="ow">in</span> <span class="n">pairs</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
        <span class="n">graph</span><span class="p">[</span><span class="n">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
    <span class="n">graph</span><span class="p">[</span><span class="n">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>

    <span class="k">if</span> <span class="n">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
        <span class="n">graph</span><span class="p">[</span><span class="n">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
    <span class="n">graph</span><span class="p">[</span><span class="n">pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">pair</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
</pre></div>

<p>Then for part 1, I generated all combinations of 3 nodes (using <code>itertools</code>) and
checked whether all 3 nodes are connected if one of them starts with <q>t</q>:</p>
<div class="highlight"><pre><span/><span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">group</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">combinations</span><span class="p">(</span><span class="n">graph</span><span class="o">.</span><span class="n">keys</span><span class="p">(),</span> <span class="mi">3</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">group</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"t"</span> <span class="ow">and</span> <span class="n">group</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"t"</span> <span class="ow">and</span> <span class="n">group</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"t"</span><span class="p">:</span>
        <span class="k">continue</span>
    <span class="k">if</span> <span class="n">group</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">group</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="ow">and</span> <span class="n">group</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">group</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span> <span class="ow">and</span> <span class="n">group</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">group</span><span class="p">[</span><span class="mi">1</span><span class="p">]]:</span>
        <span class="n">total</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>

<p>For the second part, I implemented a helper function that checks whether all
nodes in an arbitrarily long group are connected:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">all_connected</span><span class="p">(</span><span class="n">group</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">group</span><span class="p">)):</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">group</span><span class="p">)):</span>
            <span class="k">if</span> <span class="n">group</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">group</span><span class="p">[</span><span class="n">j</span><span class="p">]]:</span>
                <span class="k">return</span> <span class="kc">False</span>
    <span class="k">return</span> <span class="kc">True</span>
</pre></div>

<p>Then I simply generated all possible combinations, keeping track of the largest
group:</p>
<div class="highlight"><pre><span/><span class="n">best</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
    <span class="n">subsets</span> <span class="o">=</span> <span class="p">[</span><span class="n">combo</span> <span class="k">for</span> <span class="n">r</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">best</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">graph</span><span class="p">[</span><span class="n">k</span><span class="p">])</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="k">for</span> <span class="n">combo</span> <span class="ow">in</span> <span class="n">itertools</span><span class="o">.</span><span class="n">combinations</span><span class="p">(</span><span class="n">graph</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">r</span><span class="p">)]</span>
    <span class="k">for</span> <span class="n">subset</span> <span class="ow">in</span> <span class="n">subsets</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">all_connected</span><span class="p">([</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="nb">list</span><span class="p">(</span><span class="n">subset</span><span class="p">)):</span>
            <span class="n">best</span> <span class="o">=</span> <span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="nb">list</span><span class="p">(</span><span class="n">subset</span><span class="p">)</span>
</pre></div>

<h2>Day 24: Crossed Wires</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/24">here</a>.</p>

<p>For part 1, I preloaded the values of <code>x</code> and <code>y</code> wires in a dictionary:</p>
<div class="highlight"><pre><span/><span class="n">vals</span><span class="p">,</span> <span class="n">gates</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"input"</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span><span class="p">)</span>

<span class="n">calc</span> <span class="o">=</span> <span class="p">{</span><span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">": "</span><span class="p">)[</span><span class="mi">0</span><span class="p">]:</span> <span class="nb">int</span><span class="p">(</span><span class="n">line</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">": "</span><span class="p">)[</span><span class="mi">1</span><span class="p">])</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">vals</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)}</span>
</pre></div>

<p>Then I implemented a function to recursively compute the value of a gate:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">get_val</span><span class="p">(</span><span class="n">v</span><span class="p">):</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">],</span> <span class="nb">int</span><span class="p">):</span>
        <span class="k">match</span> <span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
            <span class="k">case</span> <span class="s2">"AND"</span><span class="p">:</span>
                <span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_val</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span> <span class="o">&amp;</span> <span class="n">get_val</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">][</span><span class="mi">2</span><span class="p">])</span>
            <span class="k">case</span> <span class="s2">"OR"</span><span class="p">:</span>
                <span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_val</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span> <span class="o">|</span> <span class="n">get_val</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">][</span><span class="mi">2</span><span class="p">])</span>
            <span class="k">case</span> <span class="s2">"XOR"</span><span class="p">:</span> 
                <span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">]</span> <span class="o">=</span> <span class="n">get_val</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">][</span><span class="mi">0</span><span class="p">])</span> <span class="o">^</span> <span class="n">get_val</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">][</span><span class="mi">2</span><span class="p">])</span>
    <span class="k">return</span> <span class="n">calc</span><span class="p">[</span><span class="n">v</span><span class="p">]</span>
</pre></div>

<p>If we already have an int in the dictionary, return that. Otherwise we
recursively get the value of the inputs. Then I loaded the gates into <code>calc</code> as
tuples of <code>(wire, gate type, wire)</code> - this is what <code>get_value()</code> expects.</p>
<div class="highlight"><pre><span/><span class="k">for</span> <span class="n">gate</span> <span class="ow">in</span> <span class="n">gates</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">):</span>
    <span class="n">expr</span><span class="p">,</span> <span class="n">to</span> <span class="o">=</span> <span class="n">gate</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" -&gt; "</span><span class="p">)</span>
    <span class="n">calc</span><span class="p">[</span><span class="n">to</span><span class="p">]</span> <span class="o">=</span> <span class="n">expr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">)</span>
</pre></div>

<p>To get the final number, we start with all the <code>z</code> wires, reverse sorted, and
build up the result from there:</p>
<div class="highlight"><pre><span/><span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">z</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">val</span><span class="p">:</span> <span class="n">val</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"z"</span><span class="p">),</span> <span class="n">calc</span><span class="p">),</span> <span class="n">reverse</span><span class="o">=</span><span class="kc">True</span><span class="p">):</span>
    <span class="n">total</span> <span class="o">&lt;&lt;=</span> <span class="mi">1</span>
    <span class="n">total</span> <span class="o">|=</span> <span class="n">get_val</span><span class="p">(</span><span class="n">z</span><span class="p">)</span>
</pre></div>

<p>Part 2 was more difficult. This one took me longest to solve out of all problems
in the event. In fact, I got to the solution doing some ad-hoc exploration,
before I had an algorithm that produces it. The key observation was that for any
\(z_n\), the wire configuration to determine whether it is 0 or 1 looks like this:</p>

<p><img src="https://vladris.com/blog/2025/01/01/gates.png" alt="image"/></p>

<p>Realizing this, I solved the problem by checking whether the wires have the
right shape. For part 2, I represented the input wires <code>x</code> and <code>y</code> as their
names:</p>
<div class="highlight"><pre><span/><span class="n">calc</span> <span class="o">=</span> <span class="p">{</span><span class="sa">f</span><span class="s2">"x</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"x</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">45</span><span class="p">)}</span> <span class="o">|</span> <span class="p">{</span><span class="sa">f</span><span class="s2">"y</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">:</span> <span class="sa">f</span><span class="s2">"y</span><span class="si">{</span><span class="n">i</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">45</span><span class="p">)}</span>
</pre></div>

<p>The values don't matter in this part. Then the rest of the graph as tuples, this
time ordered to make things easier:</p>
<div class="highlight"><pre><span/><span class="k">for</span> <span class="n">gate</span> <span class="ow">in</span> <span class="n">gates</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">):</span>
    <span class="n">expr</span><span class="p">,</span> <span class="n">to</span> <span class="o">=</span> <span class="n">gate</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" -&gt; "</span><span class="p">)</span>
    <span class="n">calc</span><span class="p">[</span><span class="n">to</span><span class="p">]</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">expr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">))</span>
</pre></div>

<p>So the gate <code>x01 AND y01 -&gt; gcq</code> would be represented as <code>calc[gcq] = ("AND",
"x01", "y01")</code>.</p>

<p>I implemented a few helper functions. First one checks that for the given key,
we have the exact operation between \(x_n\) and \(y_n\):</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">op_n</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">op</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="n">op</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"x</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"y</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">]</span>
</pre></div>

<p>So <code>op_n("gcq", "AND", 1)</code> would return <code>True</code>. Then I implemented a couple of
search functions.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">find_key</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">calc</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">==</span> <span class="n">value</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">key</span>


<span class="k">def</span><span class="w"> </span><span class="nf">find_subtree</span><span class="p">(</span><span class="n">root_op</span><span class="p">,</span> <span class="n">op</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">calc</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">root_op</span> <span class="ow">and</span> <span class="p">(</span><span class="n">op_n</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">op</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="ow">or</span> <span class="n">op_n</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">2</span><span class="p">],</span> <span class="n">op</span><span class="p">,</span> <span class="n">n</span><span class="p">)):</span>
            <span class="k">return</span> <span class="n">key</span>
</pre></div>

<p><code>find_key</code> simply finds the key for a given value in <code>calc</code>. The second one is
more interesting: it looks for a subtree with the <code>root_op</code> operation at the
root, then either on its left or right branch, the <code>op</code> operation between \(x_n\)
and \(y_n\). This would help us find subtrees matching known shapes. For example,
if I know <code>z05</code> starts with an <code>XOR</code> gate then one of its inputs is another
<code>XOR</code> gate for <code>x05</code> and <code>y05</code>, I can retrieve the key <code>z05</code> by calling
<code>find_subtree("XOR", "XOR", 5)</code>.</p>

<p>Next, I implemented functions to check parts of the tree, making sure it has the
expected shape. If the shape is not what we expect, we identified a swapped
wire. Then we can use one of the above search function to find the right wire
and correct the mistake. These checking functions either don't return anything,
or return a pair of wires that should be swapped.</p>

<p>From the top, the function to check a <code>z</code> has the right shape is:</p>
<div class="highlight"><pre><span/><span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">calc</span><span class="p">[</span><span class="s2">"z00"</span><span class="p">]</span> <span class="o">!=</span> <span class="p">[</span><span class="s2">"XOR"</span><span class="p">,</span> <span class="s2">"x00"</span><span class="p">,</span> <span class="s2">"y00"</span><span class="p">]:</span>
            <span class="k">return</span> <span class="s2">"z00"</span><span class="p">,</span> <span class="n">find_key</span><span class="p">([</span><span class="s2">"XOR"</span><span class="p">,</span> <span class="s2">"x00"</span><span class="p">,</span> <span class="s2">"y00"</span><span class="p">])</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">45</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">check_or</span><span class="p">(</span><span class="sa">f</span><span class="s2">"z45"</span><span class="p">,</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

    <span class="n">z</span> <span class="o">=</span> <span class="n">calc</span><span class="p">[</span><span class="sa">f</span><span class="s2">"z</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">]</span>
    <span class="k">if</span> <span class="n">z</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"XOR"</span><span class="p">:</span>
        <span class="k">return</span> <span class="sa">f</span><span class="s2">"z</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="n">find_subtree</span><span class="p">(</span><span class="s2">"XOR"</span><span class="p">,</span> <span class="s2">"XOR"</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">op_n</span><span class="p">(</span><span class="n">z</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"XOR"</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">check_or</span><span class="p">(</span><span class="n">z</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">elif</span> <span class="n">op_n</span><span class="p">(</span><span class="n">z</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="s2">"XOR"</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">check_or</span><span class="p">(</span><span class="n">z</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">check_or</span><span class="p">(</span><span class="n">z</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">z</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">find_key</span><span class="p">([</span><span class="s2">"XOR"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"x</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"y</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">])</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">z</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">find_key</span><span class="p">([</span><span class="s2">"XOR"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"x</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"y</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">])</span>
</pre></div>

<p>First we handle a couple of special cases. If <code>n</code> is 0, we don't have a carry,
if <code>n</code> is 45, we don't have an <code>XOR</code> at the root since \(z_{45}\) doesn't have
corresponding \(x_{45}\) and \(y_{45}\). Special cases aside, we check whether we
have an <code>XOR</code> at the root. If not, we have an issue here. We need to find the
subtree with two <code>XOR</code>s.</p>

<p>If we do have an <code>XOR</code> at the root, we check whether the left or right branch is
<code>XOR</code> between \(x_n\) and \(y_n\). If it is, we move on to check the carry subtree
by calling <code>check_or</code> (implementation below). If it isn't we have an issue here.
We search for the correct subtree and return.</p>

<p>Using the same idea, we check the subtrees for the carry rooted at <code>OR</code> and at
<code>AND</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">check_or</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">op_n</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="s2">"AND"</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span>
            <span class="k">return</span> <span class="n">key</span><span class="p">,</span> <span class="n">find_key</span><span class="p">([</span><span class="s2">"AND"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"x00"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"y00"</span><span class="p">])</span>
        <span class="k">return</span>

    <span class="k">if</span> <span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"OR"</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">key</span><span class="p">,</span> <span class="n">find_subtree</span><span class="p">(</span><span class="s2">"OR"</span><span class="p">,</span> <span class="s2">"AND"</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">op_n</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"AND"</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">check_and</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span><span class="p">)</span>
    <span class="k">elif</span> <span class="n">op_n</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">2</span><span class="p">],</span> <span class="s2">"AND"</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">check_and</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">key</span><span class="p">,</span> <span class="n">find_key</span><span class="p">([</span><span class="s2">"AND"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"x</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"y</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">])</span>


<span class="k">def</span><span class="w"> </span><span class="nf">check_and</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s2">"AND"</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">key</span><span class="p">,</span> <span class="n">find_subtree</span><span class="p">(</span><span class="s2">"AND"</span><span class="p">,</span> <span class="s2">"XOR"</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">op_n</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="s2">"XOR"</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">check_or</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">2</span><span class="p">],</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">elif</span> <span class="n">op_n</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">2</span><span class="p">],</span> <span class="s2">"XOR"</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">check_or</span><span class="p">(</span><span class="n">calc</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">key</span><span class="p">,</span> <span class="n">find_key</span><span class="p">([</span><span class="s2">"XOR"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"x</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"y</span><span class="si">{</span><span class="n">n</span><span class="si">:</span><span class="s2">02</span><span class="si">}</span><span class="s2">"</span><span class="p">])</span>
</pre></div>

<p>Then to produce the solution, we check each <code>z</code> in turn, and if <code>check_z</code>
returns two key, we add them to our result, swap their values, and continue:</p>
<div class="highlight"><pre><span/><span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">46</span><span class="p">):</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">check</span> <span class="o">:=</span> <span class="n">check_z</span><span class="p">(</span><span class="n">i</span><span class="p">))</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
        <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">check</span>
        <span class="n">result</span> <span class="o">+=</span> <span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">]</span>
        <span class="n">calc</span><span class="p">[</span><span class="n">x</span><span class="p">],</span> <span class="n">calc</span><span class="p">[</span><span class="n">y</span><span class="p">]</span> <span class="o">=</span> <span class="n">calc</span><span class="p">[</span><span class="n">y</span><span class="p">],</span> <span class="n">calc</span><span class="p">[</span><span class="n">x</span><span class="p">]</span>
</pre></div>

<p>After running this, we end up with the 8 keys we need in <code>result</code>.</p>

<p>This problem was really fun, as I had to do a bunch of exploration of the tree
shapes and of the input to come up with the solution. This only works because
all the gates conform to this shape. I can think of wiring that would still
produced the desired result but not respect this shape, in which case my
solution wouldn't work. For example, introduce somewhere an <code>OR</code> node with one
of the input wires being a value <code>XOR</code>ed with itself. That wouldn't change the
evaluation result, as the value <code>XOR</code>ed with itself would always be 0, so
whatever  the other input is, <code>OR</code>ing it with 0 would keep it unchanged. That
said, it seems all inputs were shape-conforming so checking parts of their
subtree did the trick.</p>

<h2>Day 25: Code Chronicle</h2>

<p>Problem statement is <a href="https://adventofcode.com/2024/day/25">here</a>.</p>

<p>Without converting the keys and locks to numbers, we simply need to check if any
two schematics have a <code>#</code> in any one position:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">overlap</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">l1</span><span class="p">,</span> <span class="n">l2</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">c1</span><span class="p">,</span> <span class="n">c2</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">l1</span><span class="p">,</span> <span class="n">l2</span><span class="p">):</span>
            <span class="k">if</span> <span class="n">c1</span> <span class="o">==</span> <span class="s2">"#"</span> <span class="ow">and</span> <span class="n">c2</span> <span class="o">==</span> <span class="s2">"#"</span><span class="p">:</span>
                <span class="k">return</span> <span class="kc">True</span>
    <span class="k">return</span> <span class="kc">False</span>
</pre></div>

<p>Here, <code>s1</code> and <code>s2</code> are schematics represented by arrays of strings. We don't
even care to separate the schematics into keys and locks, since all keys overlap
with each other on the bottom row and all locks overlap with each other on the
top row.</p>

<p>We check all pairs of schematics and count the ones which don't overlap to get
our solution:</p>
<div class="highlight"><pre><span/><span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">schematics</span><span class="p">)):</span>
    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">schematics</span><span class="p">)):</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">overlap</span><span class="p">(</span><span class="n">schematics</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">schematics</span><span class="p">[</span><span class="n">j</span><span class="p">]):</span>
            <span class="n">total</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>

<p>I found this year's problems to be easier than prior years. The most difficult
one for me by far was part 2 of day 24. The second one that took me a bit longer
was part 2 of day 21. I was a bit disappointed that I was able to brute-force
the solution to some of the later days. That said, it was all good fun. I always
enjoy Advent of Code and hope the tradition continues for many more decades!</p>
]]></description>
      <pubDate>Wed, 01 Jan 2025 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/12/07/notes-on-authoring-tools.html</link>
      <guid>https://vladris.com/blog/2024/12/07/notes-on-authoring-tools.html</guid>
      <title><![CDATA[Notes on Authoring Tools]]></title>
      <description><![CDATA[<h1>Notes on Authoring Tools</h1>

<p>I always enjoyed coding, and I always enjoyed writing. Over time, I made a
bunch of tools for authors, which I used myself. I believe there's still a lot
of room to improve the authoring experience. Here is a short history of some
of these past projects.</p>

<h2>Tinkerer</h2>

<p>About 12 years ago, I built <a href="https://github.com/vladris/tinkerer">Tinkerer</a>, a
now retired static website generator for blogs. This was back when Ruby was
extremely popular and many blogs were using <a href="https://jekyllrb.com/">Jekyll</a> for
their blogs.</p>

<p>I was learning Python at the time, and figured building a similar blogging
engine on Python would be a good learning exercise. I created this on top of
<a href="https://www.sphinx-doc.org/en/master/">Sphinx</a>, which is a static website
builder used for documentation. This was pretty much what everyone in the Python
world was using at the time. Tinkerer added a set of extensions for Sphinx to
provide things like categories, metadata, RSS-feed generation, plug-in Google
Analytics, comments via Disqus etc. plus a command line interface to manage blog
posts and build the website.</p>

<p>It was a neat project, with several contributors adding fixes and features to
it. I used it for many years for this blog.</p>

<p>I ended up retiring it 2 years ago. The Sphinx project made some changes in
newer versions which broke some of the functionality. I pinned the Sphinx
version but that didn't feel like a good solution. Another drawback was that
Sphinx supported reStructuredText, which was very popular, at least in the
Python world, before Markdown took over the world. Today it seems Sphinx
extended support to Markdown but as far as I know this was not the case
when I decided to retire Tinkerer.</p>

<p>It has a good run of ten years, for a small learning project I did on the side.</p>

<h2>Baku</h2>

<p>Of course, I wanted to continue building my blog with my own tools. I took the
learnings from Tinkerer and build <a href="https://github.com/vladris/baku/">Baku</a>. Baku
keeps the simple command line interface of Tinkerer, but builds from Markdown. I
also stripped it down to the features I found myself using most. Baku produces
an RSS feed, a chronological list of posts, <q>previous post</q> and <q>next post</q>
navigation, but not much else. I did away with categories, analytics, comments.</p>

<p>Some of these can be easily added if needed via the website template. Speaking
of templates, after being broken by Sphinx once, I wanted Baku to have minimal
dependencies. Sphinx uses <a href="https://jinja.palletsprojects.com/en/stable/">Jinja</a>
as a templating language out of which it builds HTML. Templates contain HTML and
placeholders with a custom expression language which is evaluated at build time.
For Baku, I was able to replace this with <a href="https://github.com/vladris/baku/blob/main/baku/templating.py">about 100 lines of code</a>,
providing a rich enough language for my needs: <code>for</code> loops, conditionals,
variable access. I called this <code>VerySimpleTemplate</code>, and in fact ended up
reusing for another static website (that was not a blog).</p>

<p>I converted my old posts from reStructuredText to Markdown using
<a href="https://pandoc.org/">Pandoc</a>, and have been using it since. The blog you're
currently reading was built with Baku.</p>

<h2>WriteRT</h2>

<p>10 years ago, the Surface tablet launched, with Windows RT and a new app store.
As another learning exercise, I built a small app for focused writing, very
much inspired by <a href="https://ia.net/writer">iA Writer</a>, which did not have a
Windows version back then.</p>

<p>I published <a href="https://apps.microsoft.com/detail/9wzdncrdn98d">WriteRT</a> to the
app store. It fared pretty well for a project I put together during the holiday
break, while I was learning the new WinRT developer platform.</p>

<h2>Other Tools</h2>

<p>Which brings us to today. Since building Tinkerer, I published quite a few blog
posts, a bunch of articles, and several books. I wish for a better tool for
long-form writing.</p>

<p>I used Word quite a bit, and not just because I've been part of the Office
organization for so many years. It is a good tool, but it is a multi-purpose
tools, not necessarily aimed at creative writing, long form writing and so on.
<a href="https://www.literatureandlatte.com/scrivener/overview">Scrivener</a> has a lot of
great features, but I don't find its look and feel very inspiring. In fact, the
best designed editors I used over the past year or so are
<a href="https://bear.app/">Bear</a> and <a href="https://obsidian.md/">Obsidian</a>. I love the
inline Markdown, where the markup disappears if not under the cursor. I love the
theming support, as I'm very particular about color schemes. I used <a href="https://ethanschoonover.com/solarized/">Solarized
Dark</a> for a long time, then more
recently switched to <a href="https://github.com/tokyo-night/tokyo-night-vscode-theme">Tokyo Night</a>.
I've also toyed with <a href="https://www.nordtheme.com/">Nord</a>. Both Bear and Obsidian
are great apps, but they are meant for note-taking. Some of the organizing
features do come in handy for some long form writing, but they are also missing
features an author would like to have handy (for example, some revision tools).</p>

<p>I know there are many other tools out there, some of them I'm not covering as
I didn't find them interesting, others I might not know about, so please
consider this a very short and incomplete summary of the landscape.</p>

<p>For my latest writing projects, I've been using Obsidian. For now.</p>

<h2>Saturn9</h2>

<p>Earlier this year, I decided to build something. I got <a href="https://saturn9.studio/">https://saturn9.studio/</a>,
and I put up a few explorations. I was originally considering building a text
editor from scratch, which I still think would be a very fun project, but a
text editor is a very complex piece of software. I might still do this at some
point in the future, as a learning exercise, but for now I settled on
<a href="https://prosemirror.net/">ProseMirror</a>, a great open-source editor with a
plug-in architecture.</p>

<p>In my spare time, I've been hacking away at a core experience. There's still a
bunch of missing features and a lot of polish that needs to happen, but I hope
to eventually bundle this into an Electron app and publish it as an app.</p>

<p>I want to start small, with an initial experience centered around
distraction-free writing. A retake on WriteRT, with better Markdown support,
a more polished experience, themes and such. Then build on top of that to add
features for what I see as the different modes for authoring:</p>

<ul>
<li>Inspiration and distraction-free writing - Have inspiration to strike and
put it all down.</li>
<li>Organizing - Managing outlines, chapters, notes, with easy navigation and
retrieval.</li>
<li>Revising - Annotating, proofreading, grammar and style checking and so on.</li>
<li>Publishing - Exporting to various formats used for web publishing, ebooks,
or print.</li>
</ul>

<p>It's slow progress, as it is a side-project, but I have a few core pieces
working to some extent.</p>

<p>Here's a demo of (a subset of) Markdown support, automatically hiding markup and
only revealing it when the cursor is on the marked element:</p>

<div id="demo1" class="editor-wrapper"/>

<p>This still has a ton of bugs to work through and polish - backspace over hidden
markup doesn't work well, new line in list should assume new list item, loading
Markdown documents needs work, formatting commands are not implemented and so
on. But I've been having fun learning about the complexities of text editors
and stitching this together.</p>

<p>Since I mentioned focused writing, here's a distraction-free experience in full
screen mode (and some inspiring placeholder text) based on the same editor. Just
start typing to see it work:</p>

<div id="demo2" class="editor-wrapper"/>

<p>I also really wanted theming support, which is fairly easy to do on the web.
This is in fact mostly CSS, less editor core, but here's an example of theme
switching between Nord and Solarized:</p>

<div>
  <label>
    <input type="radio" name="theme" value="theme1" checked="checked"/>Nord
  </label>
  <label>
    <input type="radio" name="theme" value="theme2"/>Solarized
  </label>
  <div id="demo3" class="editor-wrapper"/>
</div>

<p>Authors also care a lot about word count. Below is an example of selection-aware
word counting. Try it out by selecting different parts of the text.</p>

<div>
  <p id="word-counter"/>
  <div id="demo4" class="editor-wrapper"/>
</div>

<script src="bundle.js"/>
<script src="d.js"/>

<p>Very early alpha, but some bits work. I'm planning on polishing this over the
following months into a first version of a full-featured editor.</p>

<h3>AI</h3>

<p>Of course, I must touch on AI, since AI is everywhere nowadays. I actually have
some strong opinions on how large language models and creative writing
intersect.</p>

<p>As an author, asking AI to write something for me or rewrite something to be
more like this or more like that feels a lot like cheating. I want to use my own
voice. It's my writing, not the model's.</p>

<p>That said, LLMs bring some amazing super-powers to authors. Brainstorming is
one of them - idea generation for when you don't feel inspired. Another great
one is critique - a good model can gave you valuable feedback on strong points
and areas of improvement for your writing. Research is yet another one - I've
been asking ChatGPT questions about military ranks, slang, and so on for the
sci-fi book I'm working on.</p>

<p>I know a lot of editors are integrating AI features now, and I think most of
them are missing the mark on how to best empower authors. I want to build my
take on it, which I hopefully will in the fullness of time.</p>

<p>That said, I need a core authoring experience first, before looking into adding
AI features, so that's what I've been playing with so far. I'm optimistic of the
timing, and hope that by the time I have a solid authoring experience, models
will be commoditized enough to make the scenarios I'm thinking of lighting up
extremely cheap if not free.</p>

<p>Next year I will probably write a few blog posts on some of the interesting
challenges I encountered while working on this authoring tool.</p>
]]></description>
      <pubDate>Sat, 07 Dec 2024 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/10/28/mental-poker-part-10-conclusions.html</link>
      <guid>https://vladris.com/blog/2024/10/28/mental-poker-part-10-conclusions.html</guid>
      <title><![CDATA[Mental Poker Part 10: Conclusions]]></title>
      <description><![CDATA[<h1>Mental Poker Part 10: Conclusions</h1>

<p>This blog post will wrap up the <a href="https://vladris.com/writings/index.html#mental-poker">Mental Poker
series</a>. I started
thinking about this in 2021, and worked on a <a href="https://github.com/vladris/mental-poker-toolkit">Mental Poker
Toolkit</a> library as a
side-project. The blog posts in the series were written as I was exploring the
tech. Here I aim to bring all the pieces together in a final recap.</p>

<h2>Inception</h2>

<p>This all started with <a href="https://fluidframework.com/">Fluid Framework</a>. As the
team was building out the framework, we used hackathons to implement various
applications of Fluid. Since Fluid powers real time collaboration, team members
came up with all sorts of ideas. For example, when I joined the team, I built a
simple collaborative coloring app where multiple clients can simultaneously
color a black and white drawing. A recurring theme was games - building
multiplayer games on top of the framework. The challenge with building games is
hiding information. In Fluid, all data is synchronized to all clients and there
is no central authority. The <a href="https://learn.microsoft.com/en-us/azure/azure-fluid-relay/">Azure Fluid
Relay</a> isnât running
app code, so there isnât an easy way to maintain hidden state for a game (e.g.
cards in hand).</p>

<p>I was looking for a way to do this and learned about <a href="https://en.m.wikipedia.org/wiki/Mental_poker">mental
poker</a>. Mental Poker is a way to
play games with private information in a zero-trust environment, without relying
on a central authority to, for example, deal cards. This is a good fit for
Fluid. As a side-project, I decided to build a library to enable development of
this type of games that would work with Fluid as the underlying communication
mechanism.</p>

<p>So how do players agree on which cards they are dealt, without knowing their
opponent's hand?</p>

<h2>Cryptography</h2>

<p>The first big piece I covered was cryptography. Mental Poker relies on
commutative encryption but most commonly used encryption algorithms are
non-commutative. Commutative here meaning that if both Alice and Bob encrypt
something with their keys, it doesn't matter the order in which they apply their
keys to decrypt.</p>

<p>Since I couldn't find a library that provides a symmetric encryption algorithm,
I implemented the SRA algorithm (SRA, not RSA - same people's initials,
different algorithm). Also ended up implementing a bunch of BigInt math, all
covered in <a href="https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html">Mental Poker Part 1:
Cryptography</a>.
The blog post covers in detail how shuffling a deck of cards works and what are
the cryptography primitives used.</p>

<h2>Ledger</h2>

<p>Next, looking at game modeling, I decided a good way to represent a turn-based
game is an append-only list. Each game step is a node in the list.</p>

<p>Fluid Framework relies on Distributed Data Structures (DDSes) to maintain state
and synchronize it across clients. I implemented this ledger as a Fluid
Framework DDS <a href="https://github.com/vladris/fluid-ledger">here</a>. This is outside
of the <a href="https://github.com/vladris/mental-poker-toolkit">mental-poker-toolkit
repo</a>, since it is generally
useful outside of Mental Poker.</p>

<p>The DDS is the lowest-level representation of a game. I covered this in <a href="https://vladris.com/blog/2023/06/04/mental-poker-part-2-fluid-ledger.html">Mental
Poker Part 2: Fluid
Ledger</a>.</p>

<h2>Transport</h2>

<p>Wrapping up the plumbing, I looked as a simple abstraction over the transport
layer. This is a very simple interface:</p>
<div class="highlight"><pre><span/><span class="c1">// Transport interface</span>
<span class="k">export</span><span class="w"> </span><span class="kr">declare</span><span class="w"> </span><span class="kd">interface</span><span class="w"> </span><span class="nx">ITransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="c1">// Get all the actions that have been posted so far</span>
<span class="w">    </span><span class="nx">getActions</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// Post an action</span>
<span class="w">    </span><span class="nx">postAction</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// Event emitter</span>
<span class="w">    </span><span class="nx">once</span><span class="p">(</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="w">    </span><span class="nx">on</span><span class="p">(</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="w">    </span><span class="nx">off</span><span class="p">(</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Here, an <em>action</em> is an item on our ledger list. We can get all actions posted
to the ledger so far, post a new action, and hook up event listeners.</p>

<p>Note the interface doesn't mention the ledger, so we can swap implementations if
needed. The toolkit relies on Fluid (the <code>FluidTransport</code> implementation of this
interface) but this could be swapped out for something else as long as this
interface is satisfied.</p>

<p>I also implemented a <code>SignedTransport</code> as a decorator, which adds signature
verification for an existing <code>ITransport</code>. Since there is no central authority
and multiple clients can be part of a session, to mitigate spoofing we want
clients to exchange public keys as a first step, then sign all subsequent
messages with private keys. This a different algorithm than SRA, regular
asymmetric cryptography signing and signature verification. I implemented this
on top of
<a href="https://developer.mozilla.org/en-US/docs/Web/API/Crypto/subtle"><code>crypto.subtle</code></a>.</p>

<p>I covered all of this in <a href="https://vladris.com/blog/2023/11/28/mental-poker-part-3-transport.html">Mental Poker Part 3:
Transport</a>.</p>

<h2>Actions</h2>

<p>I briefly mentioned <em>actions</em> in the <strong>Ledger</strong> section. For the Mental Poker
toolkit, all actions are supposed to contain a <code>clientID</code> property, identifying
the client, and a <code>type</code>, which is a string literal, used to identify the
action. Plus any additional payload the action might need.</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">ClientId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>

<span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">BaseAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="nx">unknown</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<h2>Async Queue</h2>

<p>The async queue is something I haven't considered when starting the project, but
I realized using the <code>ITransport</code> interface is cumbersome. While it maps well
over Fluid, using it to implement games is not ergonomic.</p>

<p>The async queue provides a better interface over the transport:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">interface</span><span class="w"> </span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">T</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">enqueue</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="nx">dequeue</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The implementation itself is fairly straightforward, relying on the <code>ITransport</code>
APIs and events. With this, clients can enqueue and dequeue actions and await on
the response.</p>

<p>Both actions and the queue implementation are covered in <a href="https://vladris.com/blog/2024/03/16/mental-poker-part-4-actions-and-async-queue.html">Mental Poker Part 4:
Actions and Async
Queue</a>.</p>

<p>Note that by now, running a game using the toolkit can be done by just relying
on actions and the two queue APIs: <code>enqueue()</code> and <code>dequeue()</code>. Very simple.</p>

<h2>State Machine</h2>

<p>Of course, we need a way to model games. Game rules are implemented as sequences
of actions. An action is an atomic step. Note that a game move, for example
drawing a card, doesn't necessarily map to a single action going over the
transport. A game move, especially in the context of Mental Poker, can involve
several steps (actions) taken by the players.</p>

<p>The state machine aims to facilitate game implementation.</p>

<h3>Transitions</h3>

<p>I implemented two core state machine pieces: <em>local transitions</em> and <em>remote
transitions</em>.</p>

<p>A local transition means an action originates on our client. For example the
player decides to discard a card or, in a game of rock-paper-scissors, the
player picks between the 3 options. This means we will run some code and enqueue
an action:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">LocalTransition</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="p">,</span><span class="w"> </span><span class="nx">TContext</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>We take the queue as a parameter. The <code>context</code> can be anything, it's a way to
pass additional game state to the function.</p>

<p>A remote transition means we receive an action.</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">Transition</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="p">,</span><span class="w"> </span><span class="nx">TContext</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">TAction</span><span class="p">,</span>
<span class="w">    </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>Here, we dequeue an action and invoke the transition, passing the action as an
argument.</p>

<p>We need both of these transitions to implement a game, but we can provide a
unified abstraction:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span>
<span class="p">}</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>We can adapt a <code>Transition</code> to this type by calling dequeue on the <code>actionQueue</code>
and passing the resulting action to the <code>Transition</code>.</p>

<p>The state machine takes an array of <code>RunnableTransition</code>s and executes the code
in sequence. It also provides several helper functions:</p>

<ul>
<li><code>local()</code>, to create <code>RunnableTransition</code> from a <code>LocalTransition</code>.</li>
<li><code>transition()</code>, to create a <code>RunnableTransition</code> from a (remote) <code>Transition</code>.</li>
<li><code>repeat()</code>, to repeat a given <code>RunnableTransition</code> a <code>number</code> of times.</li>
<li><code>transitions()</code>, to convert several <code>RunnableTransition</code> or
<code>RunnableTransition[]</code> into a flat array of <code>RunnableTransition</code>.</li>
</ul>

<p>The post <a href="https://vladris.com/blog/2024/03/22/mental-poker-part-5-state-machine.html">Mental Poker Part 5: State
Machine</a>
covers the implementation in details and also shows examples of modeling rules
as transitions. Here's a rock-paper-scissors skeleton:</p>
<div class="highlight"><pre><span/><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">    </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Post our play action</span>
<span class="w">    </span><span class="p">}),</span>
<span class="w">    </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Both player and opponent need to post their encrypted selection</span>
<span class="w">    </span><span class="p">}),</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span>
<span class="w">    </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Post our reveal action</span>
<span class="w">    </span><span class="p">}),</span>
<span class="w">    </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">reveal</span><span class="o">:</span><span class="w"> </span><span class="kt">RevealAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Both player and opponent need to reveal their selection</span>
<span class="w">    </span><span class="p">}),</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span>
<span class="p">]);</span>
</pre></div>

<h2>Primitives</h2>

<p>We now have all the pieces we need to model games. The toolkit also provides
common primitives - plug &amp; play state machines to be integrated in games.</p>

<p>An example of this is card shuffling. Given a deck of cards, there is a state
machine that shuffles this deck according to the Mental Poker steps and hides
this behind a simple <code>shuffle()</code> function.</p>

<p>I cover the details of this in <a href="https://vladris.com/blog/2024/04/07/mental-poker-part-6-shuffling-implementation.html">Mental Poker Part 6: Shuffling
Implementation</a>.</p>

<p>Shuffling cards is the canonical example of Mental Poker, but building a game
requires several other common pieces. A few examples:</p>

<ul>
<li>Creating a Fluid transport (abstracting the Fluid container and connection
setup).</li>
<li>Enabling signature checking, in other words converting a given (unsigned)
<code>ITransport</code> into a <code>SignedTransport</code>.</li>
<li>Establishing turn order for multiple players and agreeing on a large shared
prime (required by RSA).</li>
</ul>

<p>I covered all of these in <a href="https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html">Mental Poker Part 7:
Primitives</a>.</p>

<p>All implementation rely on the state machine are expressed as sequences of
transitions.</p>

<h2>Games</h2>

<p>Finally, I provided a couple of sample games.</p>

<p>The first is rock-paper-scissors. Rock-paper-scissors is interesting because it
does require some cryptography, but it is much simpler than a card game. Players
simply pick between rock, paper, or scissors, encrypt their choice, then post it
(enqueue it). Once both players shared their pick, they share a key the other
player can use to decrypt their pick. Then we can see who won the game.</p>

<p>The implementation is covered in <a href="https://vladris.com/blog/2024/06/24/mental-poker-part-8-rock-paper-scissors.html">Mental Poker Part 8:
Rock-Paper-Scissors</a>.</p>

<p>Next, I implemented a more complex game: discard. In this game, players take
turns discarding cards as long as they can match the value or suit on top of the
discard pile. If they can't discard, they draw a card instead. The first player
to discard their whole hand wins. This is again a fairly simple game in terms of
rules, but requires more advance semantics like card shuffling, drawing and
discarding cards etc.</p>

<p>The implementation is covered in <a href="https://vladris.com/blog/2024/07/18/mental-poker-part-9-discard-game.html">Mental Poker Part 9: Discard
Game</a>.</p>

<h2>Zero-Trust</h2>

<p>Mental Poker enables us to play games in a zero-trust environment without a
centralized authority. Of course, there are some limitations.</p>

<p>Signature verification mitigates spoofing, but there is no way to guarantee
other clients aren't colluding over a secondary channel. This isn't a limitation
of Mental Poker, rather in general - even if we play poker with a server
handling the deal, players can cheat and talk to each other with a separate app.</p>

<p>Cryptography ensures certain type of cheating is impossible. For example in the
rock-paper-scissors example, a player can't pretend they picked something else
once their encrypted pick was shared with the other player. Similarly,
cryptography enables maintaining private state over a public channel, including
card shuffling, cards in hand etc.</p>

<p>The state machine helps model games as a sequence of steps. As long as the
clients agree on the rules and follow the steps, they can play a game. Once a
player posts an action that the other player doesn't expect, in other words is
not correct according to the game semantics, the other player can tell the game
rules are not respected. That said, there is no simple way to recover from this.
I call this the <q>flip the table</q> recourse. You can't really do much, since
there's no central authority to arbitrate this, but cryptography and the state
machine make it easy for you to tell when another player is cheating and, at the
very least, you can refuse to continue playing.</p>

<p>This was a very fun side-project I worked on, intermittently, for 3 years. I
learned a lot about Mental Poker and built a reusable toolkit for this type of
games. All code discussed in the series is available on GitHub:
<a href="https://github.com/vladris/mental-poker-toolkit/">https://github.com/vladris/mental-poker-toolkit/</a>.</p>
]]></description>
      <pubDate>Mon, 28 Oct 2024 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/07/18/mental-poker-part-9-discard-game.html</link>
      <guid>https://vladris.com/blog/2024/07/18/mental-poker-part-9-discard-game.html</guid>
      <title><![CDATA[Mental Poker Part 9: Discard Game]]></title>
      <description><![CDATA[<h1>Mental Poker Part 9: Discard Game</h1>

<p>For an overview on Mental Poker, see <a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">Mental Poker Part 0: An
Overview</a>.
Other articles in this
series:Â <strong><a href="https://vladris.com/writings/index.html#mental-poker">https://vladris.com/writings/index.html#mental-poker</a></strong>.
In the previous <a href="https://vladris.com/blog/2024/06/24/mental-poker-part-8-rock-paper-scissors.html">post in the series</a>
we looked at building a simple game of rock-paper-scissors. In this post we'll
look at implementing a card game.</p>

<h2>Overview</h2>

<p>We'll build a discard game - players take turns discarding a card that must
match either the suit or the value of the card on top of the discard pile. The
player who discards their whole hand first wins.</p>

<p>We're implementing a simple game as the focus is not on the game-specific logic,
rather how to leverage the Mental Poker toolkit.</p>

<p>The full code for this is in the
<a href="https://github.com/vladris/mental-poker-toolkit/tree/main/demos/discard"><code>demos/discard</code></a>
app. The best way to read this post is side by side with the code.</p>

<p>We'll follow a similar structure to the rock-paper-scissors game we looked at in
the <a href="https://vladris.com/blog/2024/06/24/mental-poker-part-8-rock-paper-scissors.htm">previous
post</a>:</p>

<ul>
<li>A <em>model</em> implementing the game logic.</li>
<li>A Redux <em>store</em> maintaining game state.</li>
<li>A React <em>UI</em> bound to the store.</li>
</ul>

<h2>Model</h2>

<p>First, let's look at how we implement the deck of cards and associated logic.</p>

<h3>Deck</h3>

<p>We'll represent a card as a string, for example <code>"9:hearts"</code> is the 9 of hearts.
The function <code>getDeck()</code> initializes as unshuffled deck of cards:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">getDeck</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="p">[</span><span class="s2">"9"</span><span class="p">,</span><span class="w"> </span><span class="s2">"10"</span><span class="p">,</span><span class="w"> </span><span class="s2">"J"</span><span class="p">,</span><span class="w"> </span><span class="s2">"Q"</span><span class="p">,</span><span class="w"> </span><span class="s2">"K"</span><span class="p">,</span><span class="w"> </span><span class="s2">"A"</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">suit</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="p">[</span><span class="s2">"hearts"</span><span class="p">,</span><span class="w"> </span><span class="s2">"diamonds"</span><span class="p">,</span><span class="w"> </span><span class="s2">"clubs"</span><span class="p">,</span><span class="w"> </span><span class="s2">"spades"</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">deck</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">value</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">":"</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">suit</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">deck</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>We're using fewer cards (from 9 to Aces) for this demo as the more cards we have
the more prime numbers we need to find to encrypt them and it slows things down.
Rather than implementing some loading UI, we'll just use fewer cards for the
example.</p>

<p>We need a helper function to tell us whether two cards match either value or
suit:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">matchSuitOrValue</span><span class="p">(</span><span class="nx">a</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">aValue</span><span class="p">,</span><span class="w"> </span><span class="nx">aSuit</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">a</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">bValue</span><span class="p">,</span><span class="w"> </span><span class="nx">bSuit</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">b</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">aValue</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">bValue</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">aSuit</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">bSuit</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Finally, we want a class to wrap a deck and implement the functions needed for
using it:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">Deck</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">myCards</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">othersCards</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">drawPile</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">discardPile</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">decryptedCards</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="kt">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">othersKeys</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span>
<span class="w">        </span><span class="k">private</span><span class="w"> </span><span class="nx">encryptedCards</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[],</span>
<span class="w">        </span><span class="k">private</span><span class="w"> </span><span class="nx">myKeys</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">[],</span>
<span class="w">        </span><span class="k">private</span><span class="w"> </span><span class="nx">store</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span>
<span class="w">    </span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">drawPile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">encryptedCards</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">i</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">...</span>
</pre></div>

<p>We initialize the class with an array of encrypted cards (the shuffled deck) as
<code>encryptedCards</code>, our set of SRA keys (<code>myKeys</code>) and the Redux store (<code>store</code>).</p>

<p>We also need to track cards (by index):</p>

<ul>
<li>The cards in our hand (<code>myCards</code>).</li>
<li>The cards in the other player's hand (<code>othersCards</code>).</li>
<li>The draw pile (<code>drawPile</code>).</li>
<li>The discard pile (<code>discardPile</code>).</li>
</ul>

<p>As the other player shares their encryption keys (when they reveal a card to
us), we'll store them in the <code>othersKeys</code> array. Similarly, as we decrypt cards,
we'll store them in <code>decryptedCards</code> - this is just for convenience, so we don't
have to keep decrypting the same values over and over.</p>

<p>We assume we're starting with a shuffled deck of cards as a draw pile, with no
player having cards in hand - so we initialize <code>drawPile</code> to the indexes of
<code>encryptedCards</code>.</p>

<p>Some helper functions:</p>
<div class="highlight"><pre><span/><span class="p">...</span>
<span class="w">    </span>
<span class="w">    </span><span class="nx">getKey</span><span class="p">(</span><span class="nx">index</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">SRAKeySerializationHelper</span><span class="p">.</span><span class="nx">serializeSRAKeyPair</span><span class="p">(</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">myKeys</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span>
<span class="w">        </span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">getKeyFromHand</span><span class="p">(</span><span class="nx">index</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">SRAKeySerializationHelper</span><span class="p">.</span><span class="nx">serializeSRAKeyPair</span><span class="p">(</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">myKeys</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">myCards</span><span class="p">[</span><span class="nx">index</span><span class="p">]]</span>
<span class="w">        </span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">cardAt</span><span class="p">(</span><span class="nx">index</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">decryptedCards</span><span class="p">[</span><span class="nx">index</span><span class="p">])</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">partial</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">SRA</span><span class="p">.</span><span class="nx">decryptString</span><span class="p">(</span>
<span class="w">                </span><span class="k">this</span><span class="p">.</span><span class="nx">encryptedCards</span><span class="p">[</span><span class="nx">index</span><span class="p">],</span>
<span class="w">                </span><span class="k">this</span><span class="p">.</span><span class="nx">myKeys</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span>
<span class="w">            </span><span class="p">);</span>

<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">decryptedCards</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">SRA</span><span class="p">.</span><span class="nx">decryptString</span><span class="p">(</span>
<span class="w">                </span><span class="nx">partial</span><span class="p">,</span>
<span class="w">                </span><span class="k">this</span><span class="p">.</span><span class="nx">othersKeys</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span>
<span class="w">            </span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">decryptedCards</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span><span class="o">!</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">getDrawIndex</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">drawPile</span><span class="p">[</span><span class="mf">0</span><span class="p">];</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span>
<span class="w">    </span><span class="nx">canIMove</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">(</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">drawPile</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">||</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">myCards</span><span class="p">.</span><span class="nx">some</span><span class="p">((</span><span class="nx">index</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span>
<span class="w">                </span><span class="nx">matchSuitOrValue</span><span class="p">(</span>
<span class="w">                    </span><span class="k">this</span><span class="p">.</span><span class="nx">cardAt</span><span class="p">(</span><span class="nx">index</span><span class="p">),</span>
<span class="w">                    </span><span class="k">this</span><span class="p">.</span><span class="nx">cardAt</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">[</span><span class="k">this</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">])</span>
<span class="w">                </span><span class="p">)</span>
<span class="w">            </span><span class="p">)</span>
<span class="w">        </span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="p">...</span>
</pre></div>

<p>These are pretty self-explanatory:</p>

<ul>
<li><code>getKey()</code> returns our SRA key at <code>index</code>.</li>
<li><code>getKeyFromHand()</code> returns our SRA key for a card in our hand (at <code>index</code>).</li>
<li><code>cardAt()</code> returns the decrypted card at <code>index</code>. This assumes we can decrypt
the card. If we are already storing it in <code>decryptedCards</code>, we return it from
there; otherwise we decrypt it using our key and the other player's key, then
store it in <code>decryptedCards</code>.</li>
<li><code>getDrawIndex()</code> returns the index at the top of the discard pile.</li>
<li><code>canIMove()</code> returns <code>true</code> if we can discard a card. If the discard pile is
empty, we can discard anything; otherwise at least one of the cards in our
hand needs to match the suit or value of the card on top of the discard pile.</li>
</ul>

<p>We also need to implement some functions that mutate the deck (in which case we
also need to update our view-model so our UI reflects the changes):</p>
<div class="highlight"><pre><span/><span class="p">...</span>
<span class="w">    </span><span class="k">async</span><span class="w"> </span><span class="nx">myDraw</span><span class="p">(</span><span class="nx">serializedSRAKeyPair</span><span class="o">:</span><span class="w"> </span><span class="kt">SerializedSRAKeyPair</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">drawPile</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span><span class="o">!</span><span class="p">;</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">myCards</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">index</span><span class="p">);</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">othersKeys</span><span class="p">[</span><span class="nx">index</span><span class="p">]</span><span class="w"> </span><span class="o">=</span>
<span class="w">            </span><span class="nx">SRAKeySerializationHelper</span><span class="p">.</span><span class="nx">deserializeSRAKeyPair</span><span class="p">(</span>
<span class="w">                </span><span class="nx">serializedSRAKeyPair</span>
<span class="w">            </span><span class="p">);</span>

<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">updateViewModel</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">async</span><span class="w"> </span><span class="nx">othersDraw</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">othersCards</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">drawPile</span><span class="p">.</span><span class="nx">shift</span><span class="p">()</span><span class="o">!</span><span class="p">);</span>

<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">updateViewModel</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">async</span><span class="w"> </span><span class="nx">myDiscard</span><span class="p">(</span><span class="nx">index</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">cardIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">myCards</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">index</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">)[</span><span class="mf">0</span><span class="p">];</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">cardIndex</span><span class="p">);</span>

<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">updateViewModel</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">async</span><span class="w"> </span><span class="nx">othersDiscard</span><span class="p">(</span>
<span class="w">        </span><span class="nx">index</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">,</span>
<span class="w">        </span><span class="nx">serializedSRAKeyPair</span><span class="o">:</span><span class="w"> </span><span class="kt">SerializedSRAKeyPair</span>
<span class="w">    </span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">cardIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">othersCards</span><span class="p">.</span><span class="nx">splice</span><span class="p">(</span><span class="nx">index</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">)[</span><span class="mf">0</span><span class="p">];</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">othersKeys</span><span class="p">[</span><span class="nx">cardIndex</span><span class="p">]</span><span class="w"> </span><span class="o">=</span>
<span class="w">            </span><span class="nx">SRAKeySerializationHelper</span><span class="p">.</span><span class="nx">deserializeSRAKeyPair</span><span class="p">(</span>
<span class="w">                </span><span class="nx">serializedSRAKeyPair</span>
<span class="w">            </span><span class="p">);</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">cardIndex</span><span class="p">);</span>

<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">updateViewModel</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="p">...</span>
</pre></div>

<p>The actions are:</p>

<ul>
<li><code>myDraw()</code> - we draw a card from the top of the draw pile. We need the other
player's key for this card, given as the <code>serializedSRAKeyPair</code> argument.</li>
<li><code>othersDraw()</code> - other player draws a card from the top of the draw pile. Note
the <code>Deck</code> class just maintains state, so is not responsible for sharing our
key for that card with the other player - rather we just update the state
(<code>othersCards</code> and <code>drawPile</code>).</li>
<li><code>myDiscard()</code> - we discard a card. We take the <code>index</code> of the card as an
argument.</li>
<li><code>othersDiscard()</code> - other player discards a card. We take the <code>index</code> of the
card and the other player's SRA key as arguments.</li>
</ul>

<p>Note all these functions end up calling <code>updateViewModel()</code>. That's because all
of the functions change state, so we need to update our Redux store and reflect
the changes on the UI:</p>
<div class="highlight"><pre><span/><span class="p">...</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="nx">updateViewModel</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span>
<span class="w">            </span><span class="nx">updateDeckViewModel</span><span class="p">({</span>
<span class="w">                </span><span class="nx">drawPile</span><span class="o">:</span><span class="w"> </span><span class="kt">this.drawPile.length</span><span class="p">,</span>
<span class="w">                </span><span class="nx">discardPile</span><span class="o">:</span><span class="w"> </span><span class="kt">this.discardPile.map</span><span class="p">((</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">cardAt</span><span class="p">(</span><span class="nx">i</span><span class="p">)),</span>
<span class="w">                </span><span class="nx">myCards</span><span class="o">:</span><span class="w"> </span><span class="kt">this.myCards.map</span><span class="p">((</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">cardAt</span><span class="p">(</span><span class="nx">i</span><span class="p">)),</span>
<span class="w">                </span><span class="nx">othersHand</span><span class="o">:</span><span class="w"> </span><span class="kt">this.othersCards.length</span><span class="p">,</span>
<span class="w">            </span><span class="p">})</span>
<span class="w">        </span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>We haven't looked at the Redux <code>store</code> yet. We'll cover this later on but here
we dispatch a deck view-model update. The deck view-model contains the size of
the draw pile, the cards in the discard pile and our hand, and the number of
cards in the other player's hand.</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">DeckViewModel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">drawPile</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="w">    </span><span class="nx">discardPile</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[];</span>
<span class="w">    </span><span class="nx">myCards</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[];</span>
<span class="w">    </span><span class="nx">othersHand</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">defaultDeckViewModel</span><span class="o">:</span><span class="w"> </span><span class="kt">DeckViewModel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">drawPile</span><span class="o">:</span><span class="w"> </span><span class="kt">0</span><span class="p">,</span>
<span class="w">    </span><span class="nx">discardPile</span><span class="o">:</span><span class="w"> </span><span class="p">[],</span>
<span class="w">    </span><span class="nx">myCards</span><span class="o">:</span><span class="w"> </span><span class="p">[],</span>
<span class="w">    </span><span class="nx">othersHand</span><span class="o">:</span><span class="w"> </span><span class="kt">0</span><span class="p">,</span>
<span class="p">};</span>
</pre></div>

<p>These is all the deck management logic we need. Let's move on to game <em>actions</em>.</p>

<h3>Dealing</h3>

<p>We'll be using the library-provided shuffle. We covered this in <a href="https://vladris.com/blog/2024/04/07/mental-poker-part-6-shuffling-implementation.html">part
6</a>
so we won't go over it again. This is exposed by as a <code>shuffle()</code> function. So
assuming our deck is shuffled, the first action we need to handle is <em>dealing</em>
cards. In Mental Poker, dealing a card to Bob means Alice needs to share her key
to that card. Then Bob can use his key and Alice's key to <q>see</q> the card, while
Alice cannot see it since she doesn't have Bob's key. This is the equivalent of
Bob holding a card in his hand.</p>

<p>We define a <code>DealAction</code>:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">DealAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"DealAction"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">cards</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[];</span>
<span class="w">    </span><span class="nx">keys</span><span class="o">:</span><span class="w"> </span><span class="kt">SerializedSRAKeyPair</span><span class="p">[];</span>
<span class="p">}</span>
</pre></div>

<p>Here, <code>cards</code> are the indexes of the cards in the deck and <code>keys</code> are the
corresponding SRA keys for each card. Here's the state machine for dealing cards
to both players:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">deal</span><span class="p">(</span><span class="nx">imFirst</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="p">,</span><span class="w"> </span><span class="nx">count</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">queue</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">;</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Dealing"</span><span class="p">));</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">cards</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">count</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="mf">0</span><span class="p">).</span><span class="nx">map</span><span class="p">((</span><span class="nx">_</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">imFirst</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">count</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="kt">i</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">keys</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">cards</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">card</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">getKey</span><span class="p">(</span><span class="nx">card</span><span class="p">)</span><span class="o">!</span><span class="p">);</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span><span class="w"> </span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span><span class="w"> </span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"DealAction"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">cards</span><span class="p">,</span>
<span class="w">                </span><span class="nx">keys</span><span class="w"> </span><span class="p">});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">DealAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"DealAction"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">return</span><span class="p">;</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">deck</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">;</span>

<span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">cards</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">imFirst</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">cards</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Unexpected card index"</span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>
<span class="w">                    </span><span class="k">await</span><span class="w"> </span><span class="nx">deck</span><span class="p">.</span><span class="nx">myDraw</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">keys</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="w">                </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">                    </span><span class="k">await</span><span class="w"> </span><span class="nx">deck</span><span class="p">.</span><span class="nx">othersDraw</span><span class="p">();</span>
<span class="w">                </span><span class="p">}</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">cards</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">imFirst</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                    </span><span class="k">await</span><span class="w"> </span><span class="nx">deck</span><span class="p">.</span><span class="nx">othersDraw</span><span class="p">();</span>
<span class="w">                </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">cards</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">cards</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Unexpected card index"</span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>
<span class="w">                    </span><span class="k">await</span><span class="w"> </span><span class="nx">deck</span><span class="p">.</span><span class="nx">myDraw</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">keys</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="w">                </span><span class="p">}</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">}),</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span>
<span class="w">    </span><span class="p">]),</span><span class="w"> </span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">store</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>In preparation of dealing, we:</p>

<ul>
<li>Get the async <code>queue</code> from the <code>store</code>.</li>
<li>We update the game status to <code>Dealing</code> (more details on this later).</li>
<li>We determine which cards the <em>other</em> player needs - if we're fist, we get the
first <code>count</code> cards so the other player will get the next <code>count</code> ones;
otherwise they get the first <code>count</code> cards and we get the next ones.</li>
<li>We also get the set of keys we need to share with the other player so they can
decrypt the cards they are dealt.</li>
</ul>

<p>With this done, our state machine consists of:</p>

<ul>
<li>A local transition: we enqueue a <code>DealAction</code> with the <code>cards</code> and <code>keys</code> we
determined the other player gets.</li>
<li>A remote transition, repeated twice: we expect to see two <code>DealAction</code>
actions. If we see the one we sent out (the <code>clientId</code> matches our <code>clientId</code>)
we can ignore it. If we see the <code>DealAction</code> from the other player, we update
the deck. If we are first to draw, then we call <code>deck.myDraw()</code> <code>count</code> times,
then <code>deck.othersDraw()</code> <code>count</code> times; otherwise we do it the other way
around - call <code>deck.othersDraw()</code> <code>count</code> times, then call <code>deck.myDraw()</code>
<code>count</code> times.</li>
</ul>

<p>Local transitions and remote transitions are explained in <a href="https://vladris.com/blog/2024/03/22/mental-poker-part-5-state-machine.html">part
5</a>,
in which we talked about the state machine.</p>

<h3>Drawing cards</h3>

<p>Drawing a card is a two-step process. We need to tell the other player we intend
to draw a card (from the draw pile), and they need to give us their key to that
card. Similarly, if the other player tells us they want to draw a card, we give
them our key to that card.</p>

<p>We need two actions:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">DrawRequestAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"DrawRequest"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">cardIndex</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="p">}</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">DrawResponseAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"DrawResponse"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">cardIndex</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="w">    </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">SerializedSRAKeyPair</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>If we want to draw a card, here is our state machine:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">drawCard</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">queue</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">;</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Waiting"</span><span class="p">));</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span><span class="w"> </span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span><span class="w"> </span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"DrawRequest"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">cardIndex</span><span class="o">:</span><span class="w"> </span><span class="kt">context.getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">getDrawIndex</span><span class="p">()</span><span class="w"> </span><span class="p">});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">((</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">DrawRequestAction</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"DrawRequest"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">DrawResponseAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"DrawResponse"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">myDraw</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">key</span><span class="p">);</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">    </span><span class="p">],</span><span class="w"> </span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">store</span><span class="p">);</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"OthersTurn"</span><span class="p">));</span>
<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">waitForOpponent</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>We again get the async <code>queue</code> from the <code>store</code> and update the game status. Then
we run the state machine consisting of 3 transitions:</p>

<ul>
<li>A local transition in which we post our <code>DrawRequest</code> action.</li>
<li>A remote transition in which we expect to see our <code>DrawRequest</code>.</li>
<li>A remote transition in which we expect the other player to respond with a
<code>DrawResponse</code> action, giving us the key and allowing us to draw a card.</li>
</ul>

<p>Finally, after running the state machine and drawing the card, we update the
game status again to other player's turn and call <code>waitForOpponent()</code>, which
we'll cover later.</p>

<p>This fully implements us drawing a card from the top of the discard pile and
updating the deck.</p>

<h3>Discarding cards</h3>

<p>Similar to drawing cards, we need to implement discarding cards. Discarding a
card is easier - we don't need a key from the other player, rather we just
provide the key to the card we're discarding such that the other player can
<q>see</q> it.</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">DiscardRequestAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"DiscardRequest"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">cardIndex</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">;</span>
<span class="w">    </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">SerializedSRAKeyPair</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Our <code>DiscardRequestAction</code> contains the card index and our key.</p>

<p>The corresponding state machine:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">discardCard</span><span class="p">(</span><span class="nx">index</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">queue</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">;</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Waiting"</span><span class="p">));</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span><span class="w"> </span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"DiscardRequest"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">cardIndex</span><span class="o">:</span><span class="w"> </span><span class="kt">index</span><span class="p">,</span>
<span class="w">                </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">context.getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">getKeyFromHand</span><span class="p">(</span><span class="nx">index</span><span class="p">)});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">DiscardRequestAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"DiscardRequest"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">myDiscard</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">cardIndex</span><span class="p">);</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">    </span><span class="p">],</span><span class="w"> </span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">store</span><span class="p">);</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">myCards</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Win"</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"OthersTurn"</span><span class="p">));</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="nx">waitForOpponent</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>As usual, we get the <code>queue</code> and update game state. Then we run the state
machine:</p>

<ul>
<li>A local transition posts a <code>DiscardRequest</code> with the card index and key.</li>
<li>A remote transition in which we should see our own <code>DiscardRequest</code> - since
this round-tripped, we can now update the deck.</li>
</ul>

<p>After running the state machine, we need to check whether we discarded the last
card in our hand. If we did, we can update the game state to us winning.
Otherwise we wait for the other player's move.</p>

<h3>Can't move</h3>

<p>The last action we need to look at is the situation in which we can't discard
any card (no matching suit or value) and we also can't draw a card (draw pile is
empty). In this case we lose the game. Since it is our turn, we need to let the
other player know that we're not pondering our next move, rather that we can't
do anything and we lose. We'll model this as a simple <code>CantMoveAction</code>:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">CantMoveAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"CantMove"</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This action has no payload. The state machine is also very simple:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">cantMove</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">queue</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">;</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span><span class="w"> </span>
<span class="w">        </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">store.getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span><span class="w"> </span>
<span class="w">        </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"CantMove"</span><span class="w"> </span><span class="p">});</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Loss"</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>At the end of it, we update the game status to us losing.</p>

<p>So far, we have the 3 possible actions we can take when it is our turn:</p>

<ul>
<li>Draw a card (via <code>drawCard()</code>).</li>
<li>Discard a card (via <code>discardCard()</code>).</li>
<li>Can't draw, can't discard (via <code>cantMove()</code>).</li>
</ul>

<p>Next, we need to model responding to the other player's move.</p>

<h3>Opponent's turn</h3>

<p>The opponent can take the same actions as we can, so we don't need to declare
any new action types, rather we need a state machine that responds to actions
incoming from the other player:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">waitForOpponent</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">queue</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">;</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">othersAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">dequeue</span><span class="p">();</span>

<span class="w">    </span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="nx">othersAction</span><span class="p">.</span><span class="kr">type</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="s2">"DrawRequest"</span><span class="o">:</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">([</span>
<span class="w">                </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">othersAction</span><span class="p">.</span><span class="nx">cardIndex</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">getDrawIndex</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid card index for draw"</span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>

<span class="w">                    </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                        </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">store.getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span>
<span class="w">                        </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"DrawResponse"</span><span class="p">,</span>
<span class="w">                        </span><span class="nx">cardIndex</span><span class="o">:</span><span class="w"> </span><span class="kt">othersAction.cardIndex</span><span class="p">,</span>
<span class="w">                        </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">store.getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">getKey</span><span class="p">(</span><span class="nx">othersAction</span><span class="p">.</span><span class="nx">cardIndex</span><span class="p">)</span>
<span class="w">                    </span><span class="p">})}),</span>
<span class="w">                </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">DrawResponseAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"DrawResponse"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>

<span class="w">                    </span><span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">othersDraw</span><span class="p">();</span>
<span class="w">                </span><span class="p">})],</span><span class="w"> </span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">store</span><span class="p">);</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"MyTurn"</span><span class="p">));</span>
<span class="w">            </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="s2">"DiscardRequest"</span><span class="o">:</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">.</span><span class="nx">othersDiscard</span><span class="p">(</span><span class="nx">othersAction</span><span class="p">.</span><span class="nx">cardIndex</span><span class="p">,</span><span class="w"> </span><span class="nx">othersAction</span><span class="p">.</span><span class="nx">key</span><span class="p">);</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">othersHand</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Loss"</span><span class="p">));</span>
<span class="w">            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">store</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">deck</span><span class="p">.</span><span class="nx">value</span><span class="o">?</span><span class="p">.</span><span class="nx">canIMove</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"MyTurn"</span><span class="p">));</span>
<span class="w">            </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">await</span><span class="w"> </span><span class="nx">cantMove</span><span class="p">();</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="s2">"CantMove"</span><span class="o">:</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Win"</span><span class="p">));</span>
<span class="w">            </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>We dequeue an action, then we respond based on its type:</p>

<ul>
<li>If this is a <code>DrawRequest</code>, we send a <code>DrawResponse</code>. We implement this as a
simple state machine with a local transition (our <code>DrawResponse</code>) and a remote
transition in which we expect to see our response round-tripped. We also check
to ensure the draw request card index matches the top of the draw pile
(otherwise the other player might trick us and draw some other card).</li>
<li>If this is a <code>DiscardRequest</code>, we update the deck. If the other player
discarded their last card, we lose. Otherwise, if we can move, we update game
status to <code>MyTurn</code> and let the user pick which card to discard etc. But if we
can't move - can't discard anything, can't draw, then we automatically call
<code>cantMove()</code> to mark the fact we lost.</li>
<li>If this is a <code>CantMove</code>, the other player lost so we update game status to
<code>Win</code>.</li>
</ul>

<p>Note for the discard request, to keep things simple, we aren't checking whether
the move is legal. If we want to secure the implementation, we should check that
the card the other player is discarding matches either the suit or value of the
card on top of the discard pile.</p>

<h3>Actions and status</h3>

<p>We already covered all possible actions:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">Action</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">DealAction</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">DrawRequestAction</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">DrawResponseAction</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">DiscardRequestAction</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">CantMoveAction</span><span class="p">;</span>
</pre></div>

<p>The possible game status:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">GameStatus</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Waiting"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Shuffling"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Dealing"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"MyTurn"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"OthersTurn"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Win"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Loss"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Draw"</span><span class="p">;</span>
</pre></div>

<p>We just implemented all the game logic - the possible actions a player can take,
and the request/response needed to model the game of discard. We have the full
model, so let's move on to the Redux store.</p>

<h2>Store</h2>

<p>Like in the <a href="https://vladris.com/blog/2024/06/24/mental-poker-part-8-rock-paper-scissors.html">previous
post</a>,
we will be using <a href="https://redux.js.org/">Redux</a> and the <a href="https://redux-toolkit.js.org/">Redux
Toolkit</a>.</p>

<p>The sate we'll be maintaining:</p>

<ul>
<li>Our ID.</li>
<li>The other player's ID.</li>
<li>The Mental Poker async queue we implement the game on top of.</li>
<li>The game status (<code>GameStatus</code> in our model).</li>
<li>The deck (represented by an instance of <code>Deck</code>).</li>
<li>The deck view-model (providing just enough data to bind to the UI).</li>
</ul>

<p>Using <code>createAction</code> from the Redux Toolkit:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">updateId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"id/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateOtherPlayer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"otherPlayer/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateQueue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;&gt;</span><span class="p">(</span><span class="s2">"queue/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateGameStatus</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="nx">GameStatus</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"gameStatus/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateDeck</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="nx">Deck</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"deck/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateDeckViewModel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="nx">DeckViewModel</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"deckViewModel/update"</span><span class="p">);</span>
</pre></div>

<p>We'll also use the same helper to create Redux reducers as for
rock-paper-scissors:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">makeUpdateReducer</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">initialValue</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span>
<span class="w">    </span><span class="nx">updateAction</span><span class="o">:</span><span class="w"> </span><span class="kt">ReturnType</span><span class="o">&lt;</span><span class="ow">typeof</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&gt;</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">createReducer</span><span class="p">({</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">initialValue</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">builder</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">builder</span><span class="p">.</span><span class="nx">addCase</span><span class="p">(</span><span class="nx">updateAction</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">action</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">state</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">payload</span><span class="p">;</span>
<span class="w">        </span><span class="p">});</span>
<span class="w">    </span><span class="p">});</span>
<span class="p">}</span>
</pre></div>

<p>Our Redux store is:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">store</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">configureStore</span><span class="p">({</span>
<span class="w">    </span><span class="nx">reducer</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="nx">updateId</span><span class="p">),</span>
<span class="w">        </span><span class="nx">otherPlayer</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="p">(</span><span class="s2">"Not joined"</span><span class="p">,</span><span class="w"> </span><span class="nx">updateOtherPlayer</span><span class="p">),</span>
<span class="w">        </span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="o">&lt;</span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">            </span><span class="kc">undefined</span><span class="p">,</span>
<span class="w">            </span><span class="nx">updateQueue</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">        </span><span class="nx">gameStatus</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="p">(</span><span class="s2">"Waiting"</span><span class="p">,</span><span class="w"> </span><span class="nx">updateGameStatus</span><span class="p">),</span>
<span class="w">        </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="o">&lt;</span><span class="nx">Deck</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="o">&gt;</span><span class="p">(</span><span class="kc">undefined</span><span class="p">,</span><span class="w"> </span><span class="nx">updateDeck</span><span class="p">),</span>
<span class="w">        </span><span class="nx">deckViewModel</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="o">&lt;</span><span class="nx">DeckViewModel</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">defaultDeckViewModel</span><span class="p">,</span><span class="w"> </span><span class="nx">updateDeckViewModel</span><span class="p">),</span>
<span class="w">    </span><span class="p">},</span>
<span class="w">    </span><span class="nx">middleware</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">getDefaultMiddleware</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span>
<span class="w">        </span><span class="nx">getDefaultMiddleware</span><span class="p">({</span>
<span class="w">            </span><span class="nx">serializableCheck</span><span class="o">:</span><span class="w"> </span><span class="kt">false</span><span class="p">,</span>
<span class="w">        </span><span class="p">}),</span>
<span class="p">});</span>
</pre></div>

<p>This is all we need to connect the model with the view.</p>

<h2>UI</h2>

<p>We'll use React. </p>

<h3>Card</h3>

<p>The first component we need is a card:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">CardViewProps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">card</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>
<span class="w">    </span><span class="nx">onClick</span><span class="o">?:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">suiteMap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Map</span><span class="p">([</span>
<span class="w">    </span><span class="p">[</span><span class="s2">"hearts"</span><span class="p">,</span><span class="w"> </span><span class="s2">"â¥"</span><span class="p">],</span>
<span class="w">    </span><span class="p">[</span><span class="s2">"diamonds"</span><span class="p">,</span><span class="w"> </span><span class="s2">"â¦"</span><span class="p">],</span>
<span class="w">    </span><span class="p">[</span><span class="s2">"clubs"</span><span class="p">,</span><span class="w"> </span><span class="s2">"â£"</span><span class="p">],</span>
<span class="w">    </span><span class="p">[</span><span class="s2">"spades"</span><span class="p">,</span><span class="w"> </span><span class="s2">"â "</span><span class="p">]</span>
<span class="p">]);</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">CardView</span><span class="o">:</span><span class="w"> </span><span class="kt">React.FC</span><span class="o">&lt;</span><span class="nx">CardViewProps</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">({</span><span class="w"> </span><span class="nx">card</span><span class="p">,</span><span class="w"> </span><span class="nx">onClick</span><span class="w"> </span><span class="p">})</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">card</span><span class="o">?</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">)[</span><span class="mf">0</span><span class="p">];</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">suite</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">card</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="nx">suiteMap</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">card</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="s2">":"</span><span class="p">)[</span><span class="mf">1</span><span class="p">])</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">color</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">suite</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"â¥"</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">suite</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"â¦"</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"red"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"black"</span><span class="p">;</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="kt">70</span><span class="p">,</span><span class="w"> </span><span class="nx">height</span><span class="o">:</span><span class="w"> </span><span class="kt">100</span><span class="p">,</span><span class="w"> </span><span class="nx">borderColor</span><span class="o">:</span><span class="w"> </span><span class="s2">"black"</span><span class="p">,</span><span class="w"> </span><span class="nx">borderWidth</span><span class="o">:</span><span class="w"> </span><span class="kt">1</span><span class="p">,</span><span class="w"> </span><span class="nx">borderStyle</span><span class="o">:</span><span class="w"> </span><span class="s2">"solid"</span><span class="p">,</span><span class="w"> </span><span class="nx">borderRadius</span><span class="o">:</span><span class="w"> </span><span class="kt">5</span><span class="p">,</span><span class="w"> </span>
<span class="w">                    </span><span class="nx">backgroundColor</span><span class="o">:</span><span class="w"> </span><span class="kt">card</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"white"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"darkred"</span><span class="p">}}</span><span class="w"> </span><span class="nx">onClick</span><span class="o">=</span><span class="p">{</span><span class="nx">onClick</span><span class="p">}</span><span class="o">&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">display</span><span class="o">:</span><span class="w"> </span><span class="kt">card</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"block"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"none"</span><span class="p">,</span><span class="w"> </span><span class="nx">paddingLeft</span><span class="o">:</span><span class="w"> </span><span class="kt">15</span><span class="p">,</span><span class="w"> </span><span class="nx">paddingRight</span><span class="o">:</span><span class="w"> </span><span class="kt">15</span><span class="p">,</span><span class="w"> </span><span class="nx">color</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">p</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">marginTop</span><span class="o">:</span><span class="w"> </span><span class="kt">20</span><span class="p">,</span><span class="w"> </span><span class="nx">marginBottom</span><span class="o">:</span><span class="w"> </span><span class="kt">0</span><span class="p">,</span><span class="w"> </span><span class="nx">textAlign</span><span class="o">:</span><span class="w"> </span><span class="s2">"left"</span><span class="p">,</span><span class="w"> </span><span class="nx">fontSize</span><span class="o">:</span><span class="w"> </span><span class="kt">25</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span><span class="p">{</span><span class="kt">number</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">p</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">marginTop</span><span class="o">:</span><span class="w"> </span><span class="kt">0</span><span class="p">,</span><span class="w"> </span><span class="nx">textAlign</span><span class="o">:</span><span class="w"> </span><span class="s2">"right"</span><span class="p">,</span><span class="w"> </span><span class="nx">fontSize</span><span class="o">:</span><span class="w"> </span><span class="kt">30</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">suite</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">    </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="p">}</span>
</pre></div>

<p>This renders a <code>card</code> which can be a <code>string</code> or <code>undefined</code>. If it is a string,
we render the value and suit. Otherwise we render the <q>back</q> of the card - a
dark red rectangle. Cards have an optional <code>onClick()</code> event.</p>

<h3>Hand</h3>

<p>A <code>HandView</code> renders several cards:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">HandViewProps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">prefix</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">cards</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="kt">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)[];</span>
<span class="w">    </span><span class="nx">onClick</span><span class="o">?:</span><span class="w"> </span><span class="p">(</span><span class="nx">index</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="p">};</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">HandView</span><span class="o">:</span><span class="w"> </span><span class="kt">React.FC</span><span class="o">&lt;</span><span class="nx">HandViewProps</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">({</span><span class="w"> </span><span class="nx">cards</span><span class="p">,</span><span class="w"> </span><span class="nx">prefix</span><span class="p">,</span><span class="w"> </span><span class="nx">onClick</span><span class="w"> </span><span class="p">})</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">display</span><span class="o">:</span><span class="w"> </span><span class="s2">"flex"</span><span class="p">,</span><span class="w"> </span><span class="nx">flexDirection</span><span class="o">:</span><span class="w"> </span><span class="s2">"row"</span><span class="p">,</span><span class="w"> </span><span class="nx">justifyContent</span><span class="o">:</span><span class="w"> </span><span class="s2">"center"</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span><span class="p">{</span>
<span class="w">            </span><span class="nx">cards</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">card</span><span class="p">,</span><span class="w"> </span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">CardView</span><span class="w"> </span><span class="nx">key</span><span class="o">=</span><span class="p">{</span><span class="nx">prefix</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">":"</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">i</span><span class="p">}</span><span class="w"> </span><span class="nx">card</span><span class="o">=</span><span class="p">{</span><span class="w"> </span><span class="nx">card</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">onClick</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">onClick</span><span class="p">(</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}}</span><span class="w"> </span><span class="o">/&gt;</span><span class="p">)</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="p">}</span>
</pre></div>

<p>This can be the player's hand, where we should have <code>string</code> values for each
card and an <code>onClick()</code> event hooked up for when the player clicks on a card to
discard it. It can also be the other player's hand, in which case we should have
<code>undefined</code> values for each card and just show their backs.</p>

<h3>Table</h3>

<p><code>MainView</code> implements a view of the whole table:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">useSelector</span><span class="o">:</span><span class="w"> </span><span class="kt">TypedUseSelectorHook</span><span class="o">&lt;</span><span class="nx">RootState</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useReduxSelector</span><span class="p">;</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">MainView</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">idSelector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useSelector</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">otherPlayer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useSelector</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">otherPlayer</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">gameStateSelector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useSelector</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">gameStatus</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">deckViewModel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useSelector</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">deckViewModel</span><span class="p">);</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">myTurn</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">gameStateSelector</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"MyTurn"</span><span class="p">;</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">canDiscard</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="nx">index</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">matchSuitOrValue</span><span class="p">(</span>
<span class="w">            </span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">myCards</span><span class="p">[</span><span class="nx">index</span><span class="p">],</span>
<span class="w">            </span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">[</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Id</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="nx">idSelector</span><span class="p">.</span><span class="nx">value</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Other</span><span class="w"> </span><span class="nx">player</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="nx">otherPlayer</span><span class="p">.</span><span class="nx">value</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Status</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="nx">gameStateSelector</span><span class="p">.</span><span class="nx">value</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">height</span><span class="o">:</span><span class="w"> </span><span class="kt">200</span><span class="p">,</span><span class="w"> </span><span class="nx">textAlign</span><span class="o">:</span><span class="w"> </span><span class="s2">"center"</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">HandView</span><span class="w"> </span><span class="nx">prefix</span><span class="o">=</span><span class="p">{</span><span class="s2">"others"</span><span class="p">}</span><span class="w"> </span><span class="nx">cards</span><span class="o">=</span><span class="p">{</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">othersHand</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="kc">undefined</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">height</span><span class="o">:</span><span class="w"> </span><span class="kt">200</span><span class="p">,</span><span class="w"> </span><span class="nx">display</span><span class="o">:</span><span class="w"> </span><span class="s2">"flex"</span><span class="p">,</span><span class="w"> </span><span class="nx">flexDirection</span><span class="o">:</span><span class="w"> </span><span class="s2">"row"</span><span class="p">,</span><span class="w"> </span><span class="nx">justifyContent</span><span class="o">:</span><span class="w"> </span><span class="s2">"center"</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">display</span><span class="o">:</span><span class="w"> </span><span class="kt">deckViewModel.value.drawPile</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"block"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"none"</span><span class="p">,</span><span class="w"> </span><span class="nx">margin</span><span class="o">:</span><span class="w"> </span><span class="kt">5</span><span class="w"> </span><span class="p">}}</span><span class="w"> </span><span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">myTurn</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">drawCard</span><span class="p">()}</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span>
<span class="w">                </span><span class="o">&lt;</span><span class="nx">span</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">drawPile</span><span class="p">}</span><span class="w"> </span><span class="nx">card</span><span class="p">{</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">drawPile</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"s"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">""</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/span&gt;</span>
<span class="w">                </span><span class="o">&lt;</span><span class="nx">CardView</span><span class="w"> </span><span class="nx">card</span><span class="o">=</span><span class="p">{</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">display</span><span class="o">:</span><span class="w"> </span><span class="kt">deckViewModel.value.discardPile.length</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mf">0</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"block"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"none"</span><span class="p">,</span><span class="w"> </span><span class="nx">margin</span><span class="o">:</span><span class="w"> </span><span class="kt">5</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span>
<span class="w">                </span><span class="o">&lt;</span><span class="nx">span</span><span class="o">&gt;</span><span class="p">{</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">length</span><span class="p">}</span><span class="w"> </span><span class="nx">card</span><span class="p">{</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="mf">1</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"s"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">""</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/span&gt;</span>
<span class="w">                </span><span class="o">&lt;</span><span class="nx">CardView</span><span class="w"> </span><span class="nx">card</span><span class="o">=</span><span class="p">{</span><span class="w"> </span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">[</span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">discardPile</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">1</span><span class="p">]</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">div</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">height</span><span class="o">:</span><span class="w"> </span><span class="kt">200</span><span class="p">,</span><span class="w"> </span><span class="nx">textAlign</span><span class="o">:</span><span class="w"> </span><span class="s2">"center"</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span>
<span class="w">            </span><span class="o">&lt;</span><span class="nx">HandView</span>
<span class="w">                </span><span class="nx">prefix</span><span class="o">=</span><span class="p">{</span><span class="s2">"mine"</span><span class="p">}</span>
<span class="w">                </span><span class="nx">cards</span><span class="o">=</span><span class="p">{</span><span class="w"> </span><span class="nx">deckViewModel</span><span class="p">.</span><span class="nx">value</span><span class="p">.</span><span class="nx">myCards</span><span class="w"> </span><span class="p">}</span>
<span class="w">                </span><span class="nx">onClick</span><span class="o">=</span><span class="p">{(</span><span class="nx">index</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">myTurn</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">canDiscard</span><span class="p">(</span><span class="nx">index</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">discardCard</span><span class="p">(</span><span class="nx">index</span><span class="p">)</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}}</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">    </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
</pre></div>

<p>This consists of:</p>

<ul>
<li>A top display showing our ID, the other player's ID, and the game status.</li>
<li>The other player's hand (we'll only see the back of the cards).</li>
<li>The draw pile - if there's no more cards in the draw pile, we don't show
anything; otherwise we show the back of a card and the number of cards in the
pile.</li>
<li>The discard pile - if nothing discarded yet, we don't show anything; otherwise
we show the card on top of the discard pile and the number of cards in the
pile.</li>
<li>Our hand.</li>
</ul>

<p>If it is our turn, we hook up <code>drawCard()</code> to the draw pile's <code>onClick()</code> and
for each card we can discard, we hook up <code>discardCard()</code> to the card's
<code>onClick()</code>.</p>

<p>And that's it. Rendering it all on the page:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">createRoot</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">"root"</span><span class="p">)</span><span class="o">!</span><span class="p">);</span>
<span class="nx">root</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span>
<span class="w">    </span><span class="o">&lt;</span><span class="nx">Provider</span><span class="w"> </span><span class="nx">store</span><span class="o">=</span><span class="p">{</span><span class="nx">store</span><span class="p">}</span><span class="o">&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">MainView</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">    </span><span class="o">&lt;</span><span class="err">/Provider&gt;</span>
<span class="p">);</span>
</pre></div>

<p>Here,Â <code>Provider</code>Â comes from theÂ <code>react-redux</code>Â package and makes the Redux store
available to the React components.</p>

<h2>Initialization</h2>

<p>Like with rock-paper-scissors, let's look at how we initialize the game:</p>
<div class="highlight"><pre><span/><span class="nx">getLedger</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="p">().</span><span class="nx">then</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">ledger</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">randomClientId</span><span class="p">();</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateId</span><span class="p">(</span><span class="nx">id</span><span class="p">));</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">upgradeTransport</span><span class="p">(</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">ledger</span><span class="p">);</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateQueue</span><span class="p">(</span><span class="nx">queue</span><span class="p">));</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">action</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">ledger</span><span class="p">.</span><span class="nx">getActions</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">id</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateOtherPlayer</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">));</span>
<span class="w">            </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">sharedPrime</span><span class="p">,</span><span class="w"> </span><span class="nx">turnOrder</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">establishTurnOrder</span><span class="p">(</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">queue</span><span class="p">);</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Shuffling"</span><span class="p">));</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">keys</span><span class="p">,</span><span class="w"> </span><span class="nx">deck</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">shuffle</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">turnOrder</span><span class="p">,</span><span class="w"> </span><span class="nx">sharedPrime</span><span class="p">,</span><span class="w"> </span><span class="nx">getDeck</span><span class="p">(),</span><span class="w"> </span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="mf">64</span><span class="p">);</span>
<span class="w"> </span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">imFirst</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">turnOrder</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">id</span><span class="p">;</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateDeck</span><span class="p">(</span><span class="ow">new</span><span class="w"> </span><span class="nx">Deck</span><span class="p">(</span><span class="nx">deck</span><span class="p">,</span><span class="w"> </span><span class="nx">keys</span><span class="p">,</span><span class="w"> </span><span class="nx">store</span><span class="p">)));</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">deal</span><span class="p">(</span><span class="nx">imFirst</span><span class="p">,</span><span class="w"> </span><span class="mf">5</span><span class="p">);</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="nx">imFirst</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="s2">"MyTurn"</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="s2">"OthersTurn"</span><span class="p">));</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">imFirst</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="nx">waitForOpponent</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">});</span>
</pre></div>

<ul>
<li>We connect to the Fluid session and get a reference to theÂ <code>ledger</code>, as we saw
inÂ <a href="https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html">part 7</a>.</li>
<li>We generate a random client ID (using the implementation
inÂ <a href="https://github.com/vladris/mental-poker-toolkit/blob/main/packages/primitives/src/randomClientId.ts"><code>packages/primitives/src/randomClientId.ts</code></a>).</li>
<li>Update our ID in the Redux store.</li>
<li>We callÂ <code>upgradeTransport()</code>Â (also discussed in <a href="https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html">part 7</a>).</li>
<li>Update the Redux store with a reference to the async queue.</li>
<li>We retrieve and store the other playerâs ID.</li>
<li>We get the shared prime and establish turn order (also covered in <a href="https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html">part 7</a>).</li>
<li>We update the game status to <code>Shuffling</code>.</li>
<li>We shuffle the deck using the <code>shuffle()</code> primitive and get back our keys and
encrypted cards.</li>
<li>Determine whether we are first (based on established turn order) and store
this in <code>imFirst</code>.</li>
<li>We instantiate a <code>Deck</code> and store in the Redux <code>store</code>.</li>
<li>Deal 5 cards to each player using <code>deal()</code>.</li>
<li>Update state again, based on whether we are first or not to <code>MyTurn</code> or
<code>OthersTurn</code>.</li>
<li>If we're not first to play, call <code>waitForOpponent()</code>.</li>
</ul>

<p>This initialization is a bit longer than the one for rock-paper-scissors, since
we have to shuffle and deal cards, and the order in which the players go is
important.</p>

<h2>Summary</h2>

<p>We looked at implementing a discard card game using the Mental Poker toolkit.
The full source code for the demo is underÂ <a href="https://github.com/vladris/mental-poker-toolkit/tree/main/demos/discard"><code>demos/discard</code></a>.</p>

<ul>
<li>Instructions on how to run the game inÂ <a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/discard/README.md"><code>README.md</code></a>.</li>
<li>Deck management is implemented in <a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/discard/src/deck.ts"><code>deck.ts</code></a>.</li>
<li>The rest of the model is implemented in <a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/discard/src/model.ts"><code>model.ts</code></a>.</li>
<li>The Redux store is implemented in <a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/discard/src/store.ts"><code>store.ts</code></a>.</li>
<li>The React components are here:
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/discard/src/cardView.tsx"><code>cardView.tsx</code></a>,
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/discard/src/handView.tsx"><code>handView.tsx</code></a>,
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/discard/src/mainView.tsx"><code>mainView.tsx</code></a>.</li>
<li>Initialization happens inÂ <a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/discard/src/index.tsx"><code>index.tsx</code></a>.</li>
</ul>

<p>We finally put the whole toolkit to its intended use and built an end-to-end interactive, 2-player card game.</p>
]]></description>
      <pubDate>Thu, 18 Jul 2024 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/06/24/mental-poker-part-8-rock-paper-scissors.html</link>
      <guid>https://vladris.com/blog/2024/06/24/mental-poker-part-8-rock-paper-scissors.html</guid>
      <title><![CDATA[Mental Poker Part 8: Rock-Paper-Scissors]]></title>
      <description><![CDATA[<h1>Mental Poker Part 8: Rock-Paper-Scissors</h1>

<p>For an overview on Mental Poker, seeÂ <strong><a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">Mental Poker Part 0: An
Overview</a></strong>.
Other articles in this
series:Â <strong><a href="https://vladris.com/writings/index.html#mental-poker">https://vladris.com/writings/index.html#mental-poker</a></strong>.
In the previousÂ <strong><a href="https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html">post in the
series</a></strong>Â we
looked at some low-level building blocks. It this post, weâll finally see how to
implement a game end-to-end using the toolkit. Weâll start with a simple game:
rock-paper-scissors.</p>

<h2>Overview</h2>

<p>Weâll build this game as a React app, using the toolkit. Weâll be using
<a href="https://redux.js.org/">Redux</a> for state management - Redux provides a good way
of binding game state to the UI, which works well with our toolkit.</p>

<p>The full code for this is in the
<a href="https://github.com/vladris/mental-poker-toolkit/tree/main/demos/rock-paper-scissors"><code>demos/rock-paper-scissors</code></a>
app.</p>

<h2>Model</h2>

<p>Since we got a lot of the primitives out of the way in the previous post (Fluid
connection, getting a <code>SignedTransport</code> etc.), in this post we can focus on the
higher level semantics of modeling the game.</p>

<p>Weâll play a round of rock-paper-scissors as follows:</p>

<ul>
<li>Both players post their selection (<code>rock</code> or <code>paper</code> or <code>scissors</code>) encrypted.</li>
<li>Both players reveal their decryption key.</li>
</ul>

<p>This 2-step protects against cheating: before the game proceeds, both players
need to make a selection. But the other player doesnât know what the selection
is until the decryption key is provided. Note for this particular game, turn
order doesnât matter.</p>

<p>Weâll start with a few type definitions:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">PlaySelection</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Rock"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Paper"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Scissors"</span><span class="p">;</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">EncryptedSelection</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
</pre></div>

<p><code>PlaySelection</code> represents the possible plays, <code>EncryptedSelection</code> is the
string representation of an encrypted <code>PlaySelection</code>.</p>

<p>Our game model will have 2 actions:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">PlayAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"PlayAction"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">encryptedSelection</span><span class="o">:</span><span class="w"> </span><span class="kt">EncryptedSelection</span><span class="p">;</span>
<span class="p">};</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">RevealAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"RevealAction"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">SerializedSRAKeyPair</span><span class="p">;</span>
<span class="p">};</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">Action</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">PlayAction</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">RevealAction</span><span class="p">;</span>
</pre></div>

<p><code>PlayAction</code> is the first step, when players post their encrypted choice.
<code>RevealAction</code> is the second step, revealing the encryption key. Weâll use the
SRA algorithm for encryption since we have it in our toolkit, but for this game
any encryption algorithm would work.</p>

<p>Weâll also need a couple more type definitions for the game state:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">GameStatus</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Waiting"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Ready"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Win"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Loss"</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="s2">"Draw"</span><span class="p">;</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">PlayValue</span><span class="w"> </span><span class="o">=</span>
<span class="w">    </span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Selection"</span><span class="p">;</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">PlaySelection</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Encrypted"</span><span class="p">;</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">EncryptedSelection</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"None"</span><span class="p">;</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">undefined</span><span class="w"> </span><span class="p">};</span>
</pre></div>

<p>The <code>GameStatus</code> represents the different states the client can be in:</p>

<ul>
<li><code>Waiting</code> for another player to connect or for round to finish.</li>
<li><code>Ready</code> to play.</li>
<li><code>Win</code>, <code>Loss</code>, <code>Draw</code> - the result after playing a round.</li>
</ul>

<p>The <code>PlayValue</code> represents the current state of a playerâs pick. It can be
either an encrypted selection, a revealed selection, or nothing (at the start of
the game).</p>

<p>Before implementing the game state machine, letâs look at the Redux store.</p>

<h2>Store</h2>

<p>I wonât go into the details of Redux in this post - please refer to the
<a href="https://redux.js.org/">Redux</a> documentation for that. Weâll be using the <a href="https://redux-toolkit.js.org/">Redux
Toolkit</a> to streamline setting up our store.</p>

<p>We will maintain 6 pieces of state:</p>

<ul>
<li>Our ID.</li>
<li>The other playerâs ID.</li>
<li>The Mental Poker async queue we implement the game on top of.</li>
<li>The game status (<code>GameStatus</code> above).</li>
<li>Our play (<code>PlayValue</code> above).</li>
<li>The other playerâs play (also a <code>PlayValue</code>).</li>
</ul>

<p>Weâll use the Redux Toolkit <code>createAction</code> helper to define the update functions
for these:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">updateId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"id/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateOtherPlayer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"otherPlayer/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateQueue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;&gt;</span><span class="p">(</span><span class="s2">"queue/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateGameStatus</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="nx">GameStatus</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"gameStatus/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateMyPlay</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="nx">PlayValue</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"myPlay/update"</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">updateTheirPlay</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&lt;</span><span class="nx">PlayValue</span><span class="o">&gt;</span><span class="p">(</span><span class="s2">"theirPlay/update"</span><span class="p">);</span>
</pre></div>

<p>Weâll also need reducers (another Redux concept) for updating the values. We can implement a helper function to create these:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">makeUpdateReducer</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">initialValue</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span>
<span class="w">    </span><span class="nx">updateAction</span><span class="o">:</span><span class="w"> </span><span class="kt">ReturnType</span><span class="o">&lt;</span><span class="ow">typeof</span><span class="w"> </span><span class="nx">createAction</span><span class="o">&gt;</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">createReducer</span><span class="p">({</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">initialValue</span><span class="w"> </span><span class="p">},</span><span class="w"> </span><span class="p">(</span><span class="nx">builder</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">builder</span><span class="p">.</span><span class="nx">addCase</span><span class="p">(</span><span class="nx">updateAction</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="w"> </span><span class="nx">action</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">state</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">payload</span><span class="p">;</span>
<span class="w">        </span><span class="p">});</span>
<span class="w">    </span><span class="p">});</span>
<span class="p">}</span>
</pre></div>

<p>Finally, we set up our Redux store as:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">store</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">configureStore</span><span class="p">({</span>
<span class="w">    </span><span class="nx">reducer</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="nx">updateId</span><span class="p">),</span>
<span class="w">        </span><span class="nx">otherPlayer</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="p">(</span><span class="s2">"Not joined"</span><span class="p">,</span><span class="w"> </span><span class="nx">updateOtherPlayer</span><span class="p">),</span>
<span class="w">        </span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="o">&lt;</span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">            </span><span class="kc">undefined</span><span class="p">,</span>
<span class="w">            </span><span class="nx">updateQueue</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">        </span><span class="nx">myPlay</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="o">&lt;</span><span class="nx">PlayValue</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">            </span><span class="p">{</span><span class="w"> </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"None"</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">undefined</span><span class="w"> </span><span class="p">},</span>
<span class="w">            </span><span class="nx">updateMyPlay</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">        </span><span class="nx">theirPlay</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="o">&lt;</span><span class="nx">PlayValue</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">            </span><span class="p">{</span><span class="w"> </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"None"</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">undefined</span><span class="w"> </span><span class="p">},</span>
<span class="w">            </span><span class="nx">updateTheirPlay</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">        </span><span class="nx">gameStatus</span><span class="o">:</span><span class="w"> </span><span class="kt">makeUpdateReducer</span><span class="p">(</span><span class="s2">"Waiting"</span><span class="p">,</span><span class="w"> </span><span class="nx">updateGameStatus</span><span class="p">),</span>
<span class="w">    </span><span class="p">},</span>
<span class="w">    </span><span class="nx">middleware</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">getDefaultMiddleware</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span>
<span class="w">        </span><span class="nx">getDefaultMiddleware</span><span class="p">({</span>
<span class="w">            </span><span class="nx">serializableCheck</span><span class="o">:</span><span class="w"> </span><span class="kt">false</span><span class="p">,</span>
<span class="w">        </span><span class="p">}),</span>
<span class="p">});</span>
</pre></div>

<p>We initialize the store with the default values:</p>

<ul>
<li>We donât have an ID.</li>
<li>The other player hasnât joined yet.</li>
<li>We donât have an async queue.</li>
<li>Neither player has any play.</li>
<li>The game state is <code>Waiting</code> (for other player to connect).</li>
</ul>

<p>Thatâs about it for Redux setup - again, I wonât cover what reducers are, how
Redux manages state changes etc.</p>

<h2>Playing a round</h2>

<p>Weâll implement playing a round of rock-paper-scissors in the function <code>async
function playRound(selection: PlaySelection)</code>. We invoke this with our selection
(rock, paper, or scissors).</p>

<p>First, we need to get a few references:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">store</span><span class="p">;</span>

<span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Waiting"</span><span class="p">));</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">queue</span><span class="p">.</span><span class="nx">value</span><span class="o">!</span><span class="p">;</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">kp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">SRA</span><span class="p">.</span><span class="nx">genereateKeyPair</span><span class="p">(</span><span class="nx">BigIntUtils</span><span class="p">.</span><span class="nx">randPrime</span><span class="p">());</span>
</pre></div>

<p>First, we get a reference to the Redux store. Then we update the game status to
<code>Waiting</code>. We get a reference to the async queue from the Redux store and,
finally, we generate an SRA key pair. The <code>generateKeyPair()</code> and <code>randPrime()</code>
functions we discussed all the way in <a href="https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html">part
1</a>,
when we covered cryptography. The <code>dispatch()</code> and <code>getState()</code> are standard
Redux calls.</p>

<p>Now letâs look at the state machine modeling a round. It consists of the
following sequence:</p>

<ol>
<li>Post our encrypted selection.</li>
<li>Expect to receive 2 encrypted selections (ours and the opponentâs).</li>
<li>Post our encryption key to reveal our selection.</li>
<li>Expect to receive 2 encryption keys (ours and the opponentâs).</li>
</ol>

<p>We can run this state machine with the Redux store as context:</p>
<div class="highlight"><pre><span/><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">playAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"PlayAction"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">encryptedSelection</span><span class="o">:</span><span class="w"> </span><span class="kt">SRA.encryptString</span><span class="p">(</span><span class="nx">selection</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="p">),</span>
<span class="w">            </span><span class="p">};</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="nx">playAction</span><span class="p">);</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">play</span><span class="o">:</span><span class="w"> </span><span class="kt">PlayAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">action</span><span class="w"> </span><span class="o">=</span>
<span class="w">            </span><span class="nx">play</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span>
<span class="w">                </span><span class="o">?</span><span class="w"> </span><span class="nx">updateMyPlay</span>
<span class="w">                </span><span class="o">:</span><span class="w"> </span><span class="kt">updateTheirPlay</span><span class="p">;</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span>
<span class="w">                </span><span class="nx">action</span><span class="p">({</span><span class="w"> </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Encrypted"</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">play.encryptedSelection</span><span class="w"> </span><span class="p">})</span>
<span class="w">        </span><span class="p">);</span>
<span class="w">        </span><span class="p">}),</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">revealAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span><span class="p">,</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"RevealAction"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeySerializationHelper.serializeSRAKeyPair</span><span class="p">(</span><span class="nx">kp</span><span class="p">),</span>
<span class="w">            </span><span class="p">};</span>
<span class="w">            </span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">(</span><span class="nx">revealAction</span><span class="p">);</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">reveal</span><span class="o">:</span><span class="w"> </span><span class="kt">RevealAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">action</span><span class="w"> </span><span class="o">=</span>
<span class="w">                </span><span class="nx">reveal</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span>
<span class="w">                    </span><span class="o">?</span><span class="w"> </span><span class="nx">updateMyPlay</span>
<span class="w">                    </span><span class="o">:</span><span class="w"> </span><span class="kt">updateTheirPlay</span><span class="p">;</span>
<span class="w">            </span><span class="kd">const</span><span class="w"> </span><span class="nx">originalValue</span><span class="w"> </span><span class="o">=</span>
<span class="w">                </span><span class="nx">reveal</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">id</span><span class="p">.</span><span class="nx">value</span>
<span class="w">                    </span><span class="o">?</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">()</span><span class="nx">.myPlay.value</span>
<span class="w">                    </span><span class="o">:</span><span class="w"> </span><span class="kt">context.getState</span><span class="p">().</span><span class="nx">theirPlay</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span>
<span class="w">                </span><span class="nx">action</span><span class="p">({</span>
<span class="w">                    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Selection"</span><span class="p">,</span>
<span class="w">                    </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">SRA.decryptString</span><span class="p">(</span>
<span class="w">                        </span><span class="nx">originalValue</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">EncryptedSelection</span><span class="p">,</span>
<span class="w">                        </span><span class="nx">SRAKeySerializationHelper</span><span class="p">.</span><span class="nx">deserializeSRAKeyPair</span><span class="p">(</span><span class="nx">reveal</span><span class="p">.</span><span class="nx">key</span><span class="p">)</span>
<span class="w">                    </span><span class="p">)</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">PlaySelection</span><span class="p">,</span>
<span class="w">                </span><span class="p">})</span>
<span class="w">            </span><span class="p">);</span>
<span class="w">        </span><span class="p">}),</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span>
<span class="w">    </span><span class="p">]),</span><span class="w"> </span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">);</span>
</pre></div>

<p>We first define a <code>local</code> transition - we enqueue our <code>PlayAction</code>.</p>

<p>We then repeat 2 times a <code>transition</code>. We update the Redux store accordingly: if
the received client ID is ours, we call <code>updateMyPlay()</code>, otherwise we call
<code>updateTheirPlay()</code> with the encrypted value.</p>

<p>Next, we enqueue our <code>RevealAction</code>.</p>

<p>We then again repeat 2 times a <code>transition</code>. If the incoming client ID is ours,
we call <code>updateMyPlay()</code> and decrypt the <code>originalValue</code> (<code>myPlay.value</code>) with
the received key, otherwise we call <code>updateTheirPlay()</code> and decrypt the
<code>originalValue</code> (<code>theirPlay.value</code>) with the received key.</p>

<p>Note how this code updates the Redux store directly, by using it as the context
for the state machine.</p>

<p>Once the state machine finishes, we should have both our play and the opponentâs
play, so we can determine the winner and update the game state accordingly:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">myPlay</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">myPlay</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">theirPlay</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">getState</span><span class="p">().</span><span class="nx">theirPlay</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>

<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">myPlay</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">theirPlay</span><span class="p">.</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Draw"</span><span class="p">));</span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="p">(</span><span class="nx">myPlay</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"Rock"</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">theirPlay</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"Scissors"</span><span class="p">)</span><span class="w"> </span><span class="o">||</span>
<span class="w">    </span><span class="p">(</span><span class="nx">myPlay</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"Paper"</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">theirPlay</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"Rock"</span><span class="p">)</span><span class="w"> </span><span class="o">||</span>
<span class="w">    </span><span class="p">(</span><span class="nx">myPlay</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"Scissors"</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="nx">theirPlay</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"Paper"</span><span class="p">)</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Win"</span><span class="p">));</span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Loss"</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>And thatâs it in terms of game mechanics. Finally, letâs look at a simple UI for
the game.</p>

<h2>UI</h2>

<p>Weâll build the UI using React. First, letâs create a component that provides
the rock-paper-scissors options as 3 buttons:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">ButtonsViewProps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">disabled</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="p">;</span>
<span class="w">    </span><span class="nx">onPlay</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">play</span><span class="o">:</span><span class="w"> </span><span class="kt">PlaySelection</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">ButtonsView</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">({</span><span class="w"> </span><span class="nx">disabled</span><span class="p">,</span><span class="w"> </span><span class="nx">onPlay</span><span class="w"> </span><span class="p">}</span><span class="o">:</span><span class="w"> </span><span class="nx">ButtonsViewProps</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">button</span><span class="w"> </span><span class="nx">disabled</span><span class="o">=</span><span class="p">{</span><span class="nx">disabled</span><span class="p">}</span><span class="w"> </span><span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">onPlay</span><span class="p">(</span><span class="s2">"Rock"</span><span class="p">)}</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="kt">200</span><span class="p">}}</span><span class="o">&gt;</span><span class="err">ðª¨</span><span class="o">&lt;</span><span class="err">/button&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">button</span><span class="w"> </span><span class="nx">disabled</span><span class="o">=</span><span class="p">{</span><span class="nx">disabled</span><span class="p">}</span><span class="w"> </span><span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">onPlay</span><span class="p">(</span><span class="s2">"Paper"</span><span class="p">)}</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="kt">200</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span><span class="err">ð</span><span class="o">&lt;</span><span class="err">/button&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">button</span><span class="w"> </span><span class="nx">disabled</span><span class="o">=</span><span class="p">{</span><span class="nx">disabled</span><span class="p">}</span><span class="w"> </span><span class="nx">onClick</span><span class="o">=</span><span class="p">{()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">onPlay</span><span class="p">(</span><span class="s2">"Scissors"</span><span class="p">)}</span><span class="w"> </span><span class="nx">style</span><span class="o">=</span><span class="p">{{</span><span class="w"> </span><span class="nx">width</span><span class="o">:</span><span class="w"> </span><span class="kt">200</span><span class="w"> </span><span class="p">}}</span><span class="o">&gt;</span><span class="err">âï¸</span><span class="o">&lt;</span><span class="err">/button&gt;</span>
<span class="w">    </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="p">}</span>
</pre></div>

<p>Our properties are a boolean that determines whether buttons should be enabled
or disabled and an <code>onPlay()</code> callback.</p>

<p>Our view is also very simple:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">useSelector</span><span class="o">:</span><span class="w"> </span><span class="kt">TypedUseSelectorHook</span><span class="o">&lt;</span><span class="nx">RootState</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useReduxSelector</span><span class="p">;</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">MainView</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">idSelector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useSelector</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">otherPlayer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useSelector</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">otherPlayer</span><span class="p">);</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">gameStateSelector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useSelector</span><span class="p">((</span><span class="nx">state</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">state</span><span class="p">.</span><span class="nx">gameStatus</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">div</span><span class="o">&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Id</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="nx">idSelector</span><span class="p">.</span><span class="nx">value</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Other</span><span class="w"> </span><span class="nx">player</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="nx">otherPlayer</span><span class="p">.</span><span class="nx">value</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">p</span><span class="o">&gt;</span><span class="nx">Status</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="nx">gameStateSelector</span><span class="p">.</span><span class="nx">value</span><span class="p">}</span><span class="o">&lt;</span><span class="err">/p&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">ButtonsView</span><span class="w"> </span><span class="nx">disabled</span><span class="o">=</span><span class="p">{</span><span class="nx">gameStateSelector</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="s2">"Waiting"</span><span class="p">}</span><span class="w"> </span><span class="nx">onPlay</span><span class="o">=</span><span class="p">{</span><span class="nx">playRound</span><span class="p">}</span><span class="o">&gt;&lt;</span><span class="err">/ButtonsView&gt;</span>
<span class="w">    </span><span class="o">&lt;</span><span class="err">/div&gt;</span>
<span class="p">}</span>
</pre></div>

<p>The first line is some React-Redux plumbing (via the <code>react-redux</code> package),
which allows us to grab data from the Redux store and put it in the UI.</p>

<p>Weâll be showing our ID, the other playerâs ID, the game status, and the 3
buttons. The buttons are enabled as long as the game state is no <code>Waiting</code>. Once
the user clicks a button, we simply call the <code>playRound()</code> function we looked at
in the previous section.</p>

<p>Rendering all of this on the page:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">root</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">ReactDOM</span><span class="p">.</span><span class="nx">createRoot</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s2">"root"</span><span class="p">)</span><span class="o">!</span><span class="p">);</span>
<span class="nx">root</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span>
<span class="w">    </span><span class="o">&lt;</span><span class="nx">Provider</span><span class="w"> </span><span class="nx">store</span><span class="o">=</span><span class="p">{</span><span class="nx">store</span><span class="p">}</span><span class="o">&gt;</span>
<span class="w">        </span><span class="o">&lt;</span><span class="nx">MainView</span><span class="w"> </span><span class="o">/&gt;</span>
<span class="w">    </span><span class="o">&lt;</span><span class="err">/Provider&gt;</span>
<span class="p">);</span>
</pre></div>

<p>Here, <code>Provider</code> comes from the <code>react-redux</code> package and makes the Redux store
available to the React components.</p>

<h2>Initialization</h2>

<p>We now have all the pieces into place, the only bit of code we havenât covered
is initializing the game:</p>
<div class="highlight"><pre><span/><span class="nx">getLedger</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="p">().</span><span class="nx">then</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">ledger</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">randomClientId</span><span class="p">();</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateId</span><span class="p">(</span><span class="nx">id</span><span class="p">));</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">upgradeTransport</span><span class="p">(</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">ledger</span><span class="p">);</span>
<span class="w">    </span>
<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateQueue</span><span class="p">(</span><span class="nx">queue</span><span class="p">));</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">action</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">ledger</span><span class="p">.</span><span class="nx">getActions</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nx">id</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateOtherPlayer</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">));</span>
<span class="w">            </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="nx">updateGameStatus</span><span class="p">(</span><span class="s2">"Ready"</span><span class="p">));</span>
<span class="p">});</span>
</pre></div>

<p>The steps are:</p>

<ul>
<li>We connect to the Fluid session and get a reference to the <code>ledger</code>, as we saw
in the <a href="https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html">previous
post</a>.</li>
<li>We generate a random client ID (Iâm not covering the <code>randomClientId()</code>
function in this post, but you can find the implementation in
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/packages/primitives/src/randomClientId.ts"><code>packages/primitives/src/randomClientId.ts</code></a>).</li>
<li>Update our ID in the Redux store.</li>
<li>We call <code>upgradeTransport()</code> (also discussed in the <a href="https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html">previous
post</a>).</li>
<li>Update the Redux store with a reference to the async queue.</li>
<li>We retrieve and store the other playerâs ID.</li>
<li>We update the game status to <code>Ready</code> (from the default, which is <code>Waiting</code>).</li>
</ul>

<p>The steps are pretty self-explanatory, maybe except getting the other playerâs
ID. The way that works is as follows: <code>getActions()</code> returns all actions posted
on the ledger so far. We look for an action where the client ID is different
than our client ID and store that as the other playerâs ID. We are guaranteed to
see at least one action from the other player, as we ran <code>upgradeTransport()</code>,
which under the hood performs a public key exchange.</p>

<p>And thatâs it - we have an end-to-end game of rock-paper-scissors.</p>

<h2>Summary</h2>

<p>We looked at implementing rock-paper-scissors using the Mental Poker toolkit.
The full source code for the demo is under
<a href="https://github.com/vladris/mental-poker-toolkit/tree/main/demos/rock-paper-scissors"><code>demos/rock-paper-scissors</code></a>.</p>

<ul>
<li>Instructions on how to run the game in
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/rock-paper-scissors/README.md"><code>README.md</code></a>.</li>
<li>The game model is implemented in
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/rock-paper-scissors/src/model.ts"><code>model.ts</code></a>.</li>
<li>The Redux store is implemented in
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/rock-paper-scissors/src/store.ts"><code>store.ts</code></a>.</li>
<li>The two React components are
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/rock-paper-scissors/src/buttonsView.tsx"><code>buttonsView.tsx</code></a>
and
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/rock-paper-scissors/src/mainView.tsx"><code>mainView.tsx</code></a>.</li>
<li>Initialization happens in
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/rock-paper-scissors/src/index.tsx"><code>index.tsx</code></a>.</li>
</ul>

<p>Note how easy it is to model a game if we rely on the toolkitâs primitives. We
implement the game logic in the model, relying on the toolkitâs capabilities. We
use Redux to store game state, which we can easily bind to a React view. That
said, this was a very simple game. In the next post weâll look at implementing a
card game.</p>
]]></description>
      <pubDate>Mon, 24 Jun 2024 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html</link>
      <guid>https://vladris.com/blog/2024/06/12/mental-poker-part-7-primitives.html</guid>
      <title><![CDATA[Mental Poker Part 7: Primitives]]></title>
      <description><![CDATA[<h1>Mental Poker Part 7: Primitives</h1>

<p>For an overview on Mental Poker, seeÂ <strong><a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">Mental Poker Part 0: An
Overview</a></strong>.
Other articles in this
seriesÂ <strong><a href="https://vladris.com/writings/index.html#mental-poker">here</a></strong>.
In the previousÂ <strong><a href="https://vladris.com/blog/2024/04/07/mental-poker-part-6-shuffling-implementation.html">post in the
series</a></strong>Â we
saw how to implement shuffling on top of our primitives.</p>

<p>It this post, weâll look at a few other primitives useful for implementing a
game on top of this toolkit.</p>

<h2>Creating a transport</h2>

<p>We talked about <a href="https://fluidframework.com/">Fluid Framework</a> in previous
posts. In <a href="https://vladris.com/blog/2023/06/04/mental-poker-part-2-fluid-ledger.html">part
2</a>,
we discussed the Fluid ledger, a distributed data structure which forms the
basis of our game message exchange. In <a href="https://vladris.com/blog/2023/11/28/mental-poker-part-3-transport.html">part
3</a>, we
talked about our <code>ITransport</code> interface and how we can implement it given a
ledger. We haveât covered how to get a ledger. </p>

<p>Letâs go back down the stack, all the way to Fluid Framework. Fluid Framework
expects clients to agree on the basic layout of the distributed data structures
theyâre working with. These data structures are packaged in a <em>container</em>. Note
this container has nothing to do with Docker containers, itâs simply a
definition for a set of data structures.</p>

<p>Weâll look at a simple implementation of joining a Fluid session and using a
container that includes only a ledger. We wonât even try to connect to an
instance of the Azure Fluid Relay service, rather weâll use a local server.
Instructions for connecting to a service hosted in Azure are
<a href="https://learn.microsoft.com/en-us/azure/azure-fluid-relay/how-tos/connect-fluid-azure-service">here</a>.
For our local server, we need a stub user and an <code>AzureLocalConnectionConfig</code>
including an <code>InsecureTokenProvider</code> - this is all plumbing to connect to a
local instance of the Fluid Relay service:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">user</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="s2">"userId"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"userName"</span><span class="p">,</span>
<span class="p">};</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">localConnectionConfig</span><span class="o">:</span><span class="w"> </span><span class="kt">AzureLocalConnectionConfig</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"local"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">tokenProvider</span><span class="o">:</span><span class="w"> </span><span class="kt">new</span><span class="w"> </span><span class="nx">InsecureTokenProvider</span><span class="p">(</span><span class="s2">""</span><span class="p">,</span><span class="w"> </span><span class="nx">user</span><span class="p">),</span>
<span class="w">    </span><span class="nx">endpoint</span><span class="o">:</span><span class="w"> </span><span class="s2">"http://localhost:7070"</span><span class="p">,</span>
<span class="p">};</span>
</pre></div>

<p>With this connection config, we can now define a simple container containing a <code>Ledger</code>:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">getLedger</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">ITransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">AzureClient</span><span class="p">({</span><span class="w"> </span><span class="nx">connection</span><span class="o">:</span><span class="w"> </span><span class="kt">localConnectionConfig</span><span class="w"> </span><span class="p">});</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">containerSchema</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">initialObjects</span><span class="o">:</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">myLedger</span><span class="o">:</span><span class="w"> </span><span class="kt">Ledger</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">};</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">container</span><span class="o">:</span><span class="w"> </span><span class="kt">IFluidContainer</span><span class="p">;</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">containerId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mf">1</span><span class="p">);</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">containerId</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">({</span><span class="w"> </span><span class="nx">container</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">client</span><span class="p">.</span><span class="nx">getContainer</span><span class="p">(</span>
<span class="w">            </span><span class="nx">containerId</span><span class="p">,</span>
<span class="w">            </span><span class="nx">containerSchema</span>
<span class="w">        </span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">({</span><span class="w"> </span><span class="nx">container</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">client</span><span class="p">.</span><span class="nx">createContainer</span><span class="p">(</span><span class="nx">containerSchema</span><span class="p">));</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">container</span><span class="p">.</span><span class="nx">attach</span><span class="p">();</span>
<span class="w">        </span><span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">id</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">ledger</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">container</span><span class="p">.</span><span class="nx">initialObjects</span><span class="p">.</span><span class="nx">myLedger</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">Ledger</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">makeFluidClient</span><span class="p">(</span><span class="nx">ledger</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>We check the browser windowâs URL: if it ends with a GUID, we load the
container; if not, we create a new container and add its GUID to the browser
windowâs URL. This makes it easy to connect two local clients to the same
session:</p>

<ul>
<li>We launch our web app and the first client will create a container and get a
GUID.</li>
<li>We then copy/paste the URL into a separate tab and the second client will
connect to the same session and load the container identified by the GUID.</li>
</ul>

<p>The code above can be found in the
<a href="https://github.com/vladris/mental-poker-toolkit/tree/main/demos/transport"><code>demos/transport</code></a>
package. This is used by the other demo apps. Note you need to run the Fluid
Framework local service: <code>npx @fluidframework/azure-local-service@latest</code>.</p>

<p>We now have a simple abstraction, <code>getLedger()</code>, that wraps all the Fluid
Framework-specifics and gives us back an <code>ITransport</code> interface (implemented as
a <code>FluidTransport</code>).</p>

<h2>Upgrading the transport</h2>

<p>We are building a turn-based, cryptographically secure game, so the first step
is to ensure our channel is secure and clients canât spoof each other.</p>

<p>In <a href="https://vladris.com/blog/2023/11/28/mental-poker-part-3-transport.html">part
3</a> we
looked at the <code>ITransport</code> interface, the <code>FluidTransport</code> implementation which
leverages the Fluid protocol for communication, and the <code>SignedTransport</code>
implementation which wraps the <code>FluidTransport</code> and enhances it with signature
verification.</p>

<blockquote>
<p><strong>Recap of signing</strong>: in cryptography, we do signing using a public/private
key pair. These are both generated from a shared seed. Alice can sign a message
using her private key and anyone that has the public key, including Bob, can
verify that the signature is indeed Aliceâs.</p>

<p>So given a public/private key pair \(&lt;K_{private}, K_{public}&gt;\) and some payload
\(P\), singing is a function that produces a signature given the payload and
private key \(sign(P, K_{private}) -&gt; signature\). Signature verification is a
function that takes a payload, signature, and public key and tells us whether
the signature was indeed produced by the corresponding private key \(verify(P,
signature, K_{public}) -&gt; true/false\).</p>
</blockquote>

<p>The neat thing about public/private key cryptography is that the public key,
which is required for validation, is not a secret - only the private key is.
Nobody can spoof a signature unless they have the private key (which isnât
shared), but everyone with the public key can verify that the signature comes
from the private key owner.</p>

<p>So if we start with a <code>FluidTransport</code>, we need our clients to exchange public
keys. Each client generates a public/private key pair, and posts its client ID
and public key. We use these to populate the key store.</p>

<p>We can implement this on top of the state machine we saw in <a href="https://vladris.com/blog/2024/03/22/mental-poker-part-5-state-machine.html">part
5</a>.
First, we define our action and context. As a reminder, the action is what we
send over the wire and expect to receive. The context is an object we make
available to the code we run whenever an action appears over the transport.</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">KeyExchangeAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"KeyExchange"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">publicKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span><span class="p">;</span>
<span class="p">};</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">CryptoContext</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="nx">me</span><span class="o">:</span><span class="w"> </span><span class="kt">PublicPrivateKeyPair</span><span class="p">;</span>
<span class="w">    </span><span class="nx">keyStore</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyStore</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>In our case our action contains the <code>ClientId</code>, the <code>type</code> (which is
<code>KeyExchange</code>), and a public key. Each client is expected to post this over the
transport. The context contains our <code>ClientId</code> (so we can tell whether the
message came from us or someone else), our public/private key pair, and the
<code>KeyStore</code> in which we put all <code>ClientId</code>-to-<code>Key</code> mappings.</p>

<p>A helper function to create the <code>CryptoContext</code>:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeCryptoContext</span><span class="p">(</span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">CryptoContext</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">clientId</span><span class="p">,</span>
<span class="w">        </span><span class="nx">me</span><span class="o">:</span><span class="w"> </span><span class="kt">await</span><span class="w"> </span><span class="nx">Signing</span><span class="p">.</span><span class="nx">generatePublicPrivateKeyPair</span><span class="p">(),</span>
<span class="w">        </span><span class="nx">keyStore</span><span class="o">:</span><span class="w"> </span><span class="kt">new</span><span class="w"> </span><span class="nb">Map</span><span class="o">&lt;</span><span class="nx">ClientId</span><span class="p">,</span><span class="w"> </span><span class="nx">Key</span><span class="o">&gt;</span><span class="p">(),</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>This leverages the cryptography primitives in our toolkit to generate a
public/private key pair.</p>

<p>Our sequence to be executed by the state machine is:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">makeKeyExchangeSequence</span><span class="p">(</span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span>
<span class="w">            </span><span class="k">async</span><span class="w"> </span><span class="p">(</span>
<span class="w">                </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">KeyExchangeAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">                </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">CryptoContext</span>
<span class="w">            </span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">await</span><span class="w"> </span><span class="nx">actionQueue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"KeyExchange"</span><span class="p">,</span>
<span class="w">                    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.clientId</span><span class="p">,</span>
<span class="w">                    </span><span class="nx">publicKey</span><span class="o">:</span><span class="w"> </span><span class="kt">context.me.publicKey</span><span class="p">,</span>
<span class="w">                </span><span class="p">});</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span>
<span class="w">            </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span>
<span class="w">                </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyExchangeAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">CryptoContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"KeyExchange"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>

<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Expected client ID"</span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>

<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">keyStore</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span>
<span class="w">                            </span><span class="s2">"Same client posted key multiple times"</span>
<span class="w">                        </span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>

<span class="w">                    </span><span class="nx">context</span><span class="p">.</span><span class="nx">keyStore</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">,</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">publicKey</span><span class="p">);</span>
<span class="w">                </span><span class="p">}</span>
<span class="w">            </span><span class="p">),</span>
<span class="w">            </span><span class="nx">players</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">    </span><span class="p">]);</span>
<span class="p">}</span>
</pre></div>

<p>Refer to <a href="https://vladris.com/blog/2024/03/22/mental-poker-part-5-state-machine.html">part
5</a>
for the state machine details and a more in-depth explanation of local
actions/transitions etc. Our sequence starts with a local action, meaning
originating from our client: we post our client ID and public key. Then, for the
given number of <code>players</code> we expect in the session, we repeatedly expect an
incoming action of type <code>KeyExchangeAction</code>.</p>

<p>In other words, our protocol require each client to start by posting their
public key, and each client should expect as many such key postings as clients
in the game.</p>

<p>We handle some error cases:</p>

<ul>
<li>If the incoming action type is not a <code>KeyExchangeAction</code>, one of the clients
didnât respect the protocol, so we bail.</li>
<li>If we donât have a client ID, we also bail.</li>
<li>Same if we already saw a key for this client ID - this means either a
malicious client is trying to pretend to be another client ID, or a bug in how
the protocol was implemented. Regardless, we have to bail.</li>
</ul>

<p>If we didnât hit any of these issues, then we store the client ID and key in the
<code>KeyStore</code> instance. Once the state machine executes this sequence, each client has enough
information to create a <code>SignedTransport</code>. Here is a helper function to perform
the whole key exchange:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">keyExchange</span><span class="p">(</span>
<span class="w">    </span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">,</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">,</span>
<span class="w">    </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">makeCryptoContext</span><span class="p">(</span><span class="nx">clientId</span><span class="p">);</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">keyExchangeSequence</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">makeKeyExchangeSequence</span><span class="p">(</span><span class="nx">players</span><span class="p">);</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="nx">keyExchangeSequence</span><span class="p">,</span><span class="w"> </span><span class="nx">actionQueue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">context</span><span class="p">.</span><span class="nx">me</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">keyStore</span><span class="p">]</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="kd">const</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This function takes as input the expected number of players, the ID of this
client, and an action queue (as discussed in <a href="https://vladris.com/blog/2024/03/16/mental-poker-part-4-actions-and-async-queue.html">part
4</a>).
The implementation is straight-forward:</p>

<ol>
<li>We create a <code>context</code>.</li>
<li>We generate a key exchange sequence by calling the function we just saw.</li>
<li>We use our state machine to run the sequence.</li>
<li>We return our private key and the <code>KeyStore</code> (the key store contains only
public keys).</li>
</ol>

<p>And here is a helper function that upgrades a transport to a signed one:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">upgradeTransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">,</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">,</span>
<span class="w">    </span><span class="nx">transport</span><span class="o">:</span><span class="w"> </span><span class="kt">ITransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="p">[</span><span class="nx">keyPair</span><span class="p">,</span><span class="w"> </span><span class="nx">keyStore</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">keyExchange</span><span class="p">(</span>
<span class="w">        </span><span class="nx">players</span><span class="p">,</span>
<span class="w">        </span><span class="nx">clientId</span><span class="p">,</span>
<span class="w">        </span><span class="ow">new</span><span class="w"> </span><span class="nx">ActionQueue</span><span class="p">(</span>
<span class="w">            </span><span class="nx">transport</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">unknown</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">ITransport</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">            </span><span class="kc">true</span>
<span class="w">        </span><span class="p">)</span>
<span class="w">    </span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">ActionQueue</span><span class="p">(</span>
<span class="w">        </span><span class="ow">new</span><span class="w"> </span><span class="nx">SignedTransport</span><span class="p">(</span>
<span class="w">            </span><span class="nx">transport</span><span class="p">,</span>
<span class="w">            </span><span class="p">{</span><span class="w"> </span><span class="nx">clientId</span><span class="p">,</span><span class="w"> </span><span class="nx">privateKey</span><span class="o">:</span><span class="w"> </span><span class="kt">keyPair.privateKey</span><span class="w"> </span><span class="p">},</span>
<span class="w">            </span><span class="nx">keyStore</span><span class="p">,</span>
<span class="w">            </span><span class="ow">new</span><span class="w"> </span><span class="nx">SignatureProvider</span><span class="p">()</span>
<span class="w">        </span><span class="p">)</span>
<span class="w">    </span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>This function takes the number of players, our client ID, and an <code>ITransport</code>
which doesnât support signature verification. It executes the key exchange, then
creates a <code>SignedTransport</code> since it now has all the pieces needed for that.
This function goes a step further, and also initializes an async queue on top of
the singed transport.</p>

<p>A game that uses the toolkit can go from start to a queue over a signed
transport in 3 steps:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">ledger</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">getLedger</span><span class="o">&lt;</span><span class="nx">Action</span><span class="o">&gt;</span><span class="p">();</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">id</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">randomClientId</span><span class="p">();</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">queue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">upgradeTransport</span><span class="p">(</span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">ledger</span><span class="p">);</span>
</pre></div>

<p>In this example, we call <code>getLedger()</code>, which we discussed in the first part of
this post, we generate a unique client ID, then we call <code>upgradeTransport()</code>.
With these 3 lines of code, we get an <code>ActionQueue</code> over a <code>SignedTransport</code>.</p>

<h2>Establishing turn order and shared large prime</h2>

<p>The last primitive weâll look at in this post is another key component of Mental
Poker: having clients agree who goes first, and agree on a shared large prime
(this shared prime is used to generate SRA keys, as discussed in <a href="https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html">part
1</a>).</p>

<p>These can be separate steps but we can combine them to be more efficient. To
establish turn order, we can leverage the ledger distributed data structure
which guarantees all clients get all ops in the same sequence: each client posts
<em>something</em>, then we simply use the order in which clients see these posts as
the turn order.</p>

<p>Hereâs a sketch of the state machine for this:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">EstablishTurnOrderAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">BaseAction</span><span class="p">;</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">EstablishTurnOrderContext</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="nx">turnOrder</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">[];</span>
<span class="p">};</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">makeEstablishTurnOrderSequence</span><span class="p">(</span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">EstablishTurnOrderAction</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">EstablishTurnOrderContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">actionQueue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"EstablishTurnOrder"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.clientId</span><span class="p">,</span>
<span class="w">            </span><span class="p">});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">((</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">EstablishTurnOrderAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">EstablishTurnOrderContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"EstablishTurnOrder"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">turnOrder</span><span class="p">.</span><span class="nx">find</span><span class="p">((</span><span class="nx">id</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">id</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Same client posted prime multiple times"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="nx">context</span><span class="p">.</span><span class="nx">turnOrder</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">);</span><span class="w"> </span>
<span class="w">        </span><span class="p">}),</span><span class="w"> </span><span class="nx">players</span><span class="p">)</span>
<span class="w">    </span><span class="p">]);</span>
<span class="p">}</span>
</pre></div>

<p>Our <code>EstablishTurnOrderAction</code> is an alias for <code>BaseAction</code>, as it doesnât
contain any additional information, just the client ID. The context contains our
<code>clientId</code> and the turn order array we need to populate.</p>

<p>The state machine posts our clientID as an action of type <code>EstablishTurnOrder</code>
action. Then for the given number of players, we expect an action of this type.
We check that incoming action is of this type, then we check we donât see the
same action coming multiple times from the same client. Finally, we add the
received <code>clientId</code> to the <code>turnOrder</code> array.</p>

<p>And thatâs it - once this executes, all clients will end up with the same
<code>turnOrder</code> array and will know whether it is their turn to act, or they should
be waiting for another client to take a turn.</p>

<p>We can extend this implementation to also establish a shared prime: each client
posts a prime, then the first one to arrive to others âwinsâ and becomes the
shared prime.</p>

<p>Weâll update our <code>EstablishTurnOrderAction</code> to include a prime:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">SerializedPrime</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">EstablishTurnOrderAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">BaseAction</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">prime</span><span class="o">:</span><span class="w"> </span><span class="kt">SerializedPrime</span><span class="w"> </span><span class="p">};</span>
</pre></div>

<p>We need to define a <code>SerializedPrime</code> (as a string) to work around the fact that
we canât serialize <code>BigInt</code>s using <code>JSON.stringify()</code>, which is what weâre using
to serialize actions.</p>

<p>We extend our context to also include the shared prime:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">EstablishTurnOrderContext</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="nx">prime</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>
<span class="w">    </span><span class="nx">turnOrder</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">[];</span>
<span class="p">};</span>
</pre></div>

<p>Our state machine also gets updated:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">makeEstablishTurnOrderSequence</span><span class="p">(</span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">EstablishTurnOrderAction</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">EstablishTurnOrderContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">actionQueue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"EstablishTurnOrder"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.clientId</span><span class="p">,</span>
<span class="w">                </span><span class="nx">prime</span><span class="o">:</span><span class="w"> </span><span class="kt">BigIntUtils.bigIntToString</span><span class="p">(</span><span class="nx">BigIntUtils</span><span class="p">.</span><span class="nx">randPrime</span><span class="p">()),</span>
<span class="w">            </span><span class="p">});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">((</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">EstablishTurnOrderAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">EstablishTurnOrderContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"EstablishTurnOrder"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">turnOrder</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="nx">context</span><span class="p">.</span><span class="nx">prime</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">BigIntUtils</span><span class="p">.</span><span class="nx">stringToBigInt</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">prime</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">turnOrder</span><span class="p">.</span><span class="nx">find</span><span class="p">((</span><span class="nx">id</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">id</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Same client posted prime multiple times"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="nx">context</span><span class="p">.</span><span class="nx">turnOrder</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">);</span><span class="w"> </span>
<span class="w">        </span><span class="p">}),</span><span class="w"> </span><span class="nx">players</span><span class="p">)</span>
<span class="w">    </span><span class="p">]);</span>
<span class="p">}</span>
</pre></div>

<p>The only changes are:</p>

<ol>
<li>When we enqueue our action, we generate a random prime and serialize it (we
have a utility function that does this, which I wonât describe here).</li>
<li>If our <code>turnOrder</code> array is empty, meaning we just received the first action,
we set the <code>prime</code> in the context.</li>
</ol>

<p>With these changes, after we run this state machine we have both the turn order
and a prime all clients agree on.</p>

<p>To make calling this easier, we provide a function to initialize the context:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">makeEstablishTurnOrderContext</span><span class="p">(</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">EstablishTurnOrderContext</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">clientId</span><span class="p">,</span>
<span class="w">        </span><span class="nx">prime</span><span class="o">:</span><span class="w"> </span><span class="kt">undefined</span><span class="p">,</span>
<span class="w">        </span><span class="nx">turnOrder</span><span class="o">:</span><span class="w"> </span><span class="p">[],</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>Then putting it all together:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">establishTurnOrder</span><span class="p">(</span>
<span class="w">    </span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">,</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">,</span>
<span class="w">    </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">makeEstablishTurnOrderContext</span><span class="p">(</span><span class="nx">clientId</span><span class="p">);</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">establishTurnOrderSequence</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">makeEstablishTurnOrderSequence</span><span class="p">(</span><span class="nx">players</span><span class="p">);</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="nx">establishTurnOrderSequence</span><span class="p">,</span><span class="w"> </span><span class="nx">actionQueue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">context</span><span class="p">.</span><span class="nx">prime</span><span class="o">!</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">turnOrder</span><span class="p">]</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="kd">const</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>We create a context, we create the state machine, then we run it. The function
returns the shared prime and the turn order.</p>

<h2>Summary</h2>

<p>In this post we covered a few primitives or building blocks we can use for
building games:</p>

<ul>
<li>Creating a Fluid transport, and abstracting all the details under a
<code>getLedger()</code> function. The code for this is in the <code>demo/transport</code> package,
in
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/demos/transport/src/container.ts"><code>container.ts</code></a>.</li>
<li>Upgrading the Fluid transport to a <code>SignedTransport</code> which signs outbound
actions and verifies signatures of incoming actions. The code for this is in
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/packages/primitives/src/upgradeTransport.ts"><code>packages/primitives/upgradeTransport.ts</code></a>.</li>
<li>Establish turn order for the players and agreeing on a shared large prime. The
code for this is in
<a href="https://github.com/vladris/mental-poker-toolkit/blob/main/packages/primitives/src/establishTurnOrder.ts"><code>packages/primitives/establishTurnOrder.ts</code></a>.</li>
</ul>

<p>With the primitives out of the way, in the next post weâll look at the
high-level of modeling a game using the toolkit.</p>
]]></description>
      <pubDate>Wed, 12 Jun 2024 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/04/07/mental-poker-part-6-shuffling-implementation.html</link>
      <guid>https://vladris.com/blog/2024/04/07/mental-poker-part-6-shuffling-implementation.html</guid>
      <title><![CDATA[Mental Poker Part 6: Shuffling Implementation]]></title>
      <description><![CDATA[<h1>Mental Poker Part 6: Shuffling Implementation</h1>

<p>For an overview on Mental Poker, see <a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">Mental Poker Part 0: An Overview</a>.
Other articles in this series: <a href="https://vladris.com/writings/index.html#mental-poker">https://vladris.com/writings/index.html#mental-poker</a>.
In the previous <a href="https://vladris.com/blog/2024/03/22/mental-poker-part-5-state-machine.html">post in the series</a>
we covered the state machine we use to implement game logic.</p>

<p>We now have all the pieces in place to look at a card shuffling algorithm.
Shuffling cards in a game of Mental Poker is one of the key innovations for
this type of zero-trust games. We went over the cryptography aspects of
shuffling in <a href="https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html">Part 1</a>.</p>

<p>Let's review the algorithm:</p>

<blockquote>
<ul>
<li>Alice takes a deck of cards (an array), shuffles the deck, generates
a secret key \(K_A\), and encrypts each card with \(K_A\).</li>
<li>Alice hands the shuffled and encrypted deck to Bob. At this point,
Bob doesn't know what order the cards are in (since Alice encrypted
the cards in the shuffled deck).</li>
<li>Bob takes the deck, shuffles it, generates a secret key \(K_B\), and
encrypts each card with \(K_B\).</li>
<li>Bob hands the deck to Alice. At this point, neither Alice nor Bob
know what order the cards are in. Alice got the deck back reshuffled
and re-encrypted by Bob, so she no longer knows where each card
ended up. Bob reshuffled an encrypted deck, so he also doesn't know
where each card is.</li>
</ul>

<p>At this point the cards are shuffled. In order to play, Alice and Bob
  also need the capability to look at individual cards. In order to enable
  this, the following steps must happen:</p>

<ul>
<li>Alice decrypts the shuffled deck with her secret key \(K_A\). At this
point she still doesn't know where each card is, as cards are still
encrypted with \(K_B\).</li>
<li>Alice generates a new set of secret keys, one for each card in the
deck. Assuming a 52-card deck, she generates
\(K_{A_1} ... K_{A_{52}}\) and encrypts each card in the deck with one
of the keys.</li>
<li>Alice hands the deck of cards to Bob. At this point, each card is
encrypted by Bob's key, \(B_K\), and one of Alice's keys, \(K_{A_i}\).</li>
<li>Bob decrypts the cards using his key \(K_B\). He still doesn't know
where each card is, as now the cards are encrypted with Alice's
keys.</li>
<li>Bob generates another set of secret keys, \(K_{B_1} ... K_{B_{52}}\),
and encrypts each card in the deck.</li>
<li>Now each card in the deck is encrypted with a unique key that only
Alice knows and a unique key only Bob knows.</li>
</ul>

<p>If Alice wants to look at a card, she asks Bob for his key for that
  card. For example, if Alice draws the first card, encrypted with
  \(K_{A_1}\) and \(K_{B_1}\), she asks Bob for \(K_{B_1}\). If Bob sends her
  \(K_{B_1}\), she now has both keys to decrypt the card and <q>look</q> at it.
  Bob still can't decrypt it because he doesn't have \(K_{A_1}\).</p>

<p>This way, as long as both Alice and Bob agree that one of them is
  supposed to <q>see</q> a card, they exchange keys as needed to enable this.</p>
</blockquote>

<h2>Implementation</h2>

<p>While we covered the algorithm before, we didn't have the infrastructure in
place to implement this. We now do.</p>

<h3>Types</h3>

<p>We'll start by describing our shuffle actions. As we just saw in the above
recap, we have 2 steps:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">ShuffleAction1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">BaseAction</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Shuffle1"</span><span class="p">;</span><span class="w"> </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="p">};</span>
<span class="kr">type</span><span class="w"> </span><span class="nx">ShuffleAction2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">BaseAction</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Shuffle2"</span><span class="p">;</span><span class="w"> </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="p">};</span>
</pre></div>

<p>We only need to pass around the deck of cards (encrypted or not), so we extend
the <code>BaseAction</code> type (which includes <code>ClientId</code> and <code>type</code>) to pin the type
and add the deck.</p>

<p>We need more data in the context though:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">ShuffleContext</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>
<span class="w">    </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[];</span>
<span class="w">    </span><span class="nx">imFirst</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="p">;</span>
<span class="w">    </span><span class="nx">keyProvider</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyProvider</span><span class="p">;</span>
<span class="w">    </span><span class="nx">commonKey?</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">;</span>
<span class="w">    </span><span class="nx">privateKeys?</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">[];</span>
<span class="p">};</span>
</pre></div>

<p>We need to know our <code>clientId</code>, whether we are first or second in the turn
order, we need a <code>keyProvider</code> to generate encryption keys, a <code>commonKey</code>
(that's for the first encryption step) and <code>privateKeys</code> (for the second
encryption step). We'll use the context later on, when we stich everything
together. Before that, let's look at the basic shuffling functions.</p>

<h3>Shuffling primitives</h3>

<p>First, we need a function that shuffles an array:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">shuffleArray</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">arr</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="nx">T</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">currentIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">arr</span><span class="p">.</span><span class="nx">length</span><span class="p">,</span><span class="w">  </span><span class="nx">randomIndex</span><span class="p">;</span>
<span class="w">  </span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nx">currentIndex</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">  </span>
<span class="w">      </span><span class="nx">randomIndex</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Math</span><span class="p">.</span><span class="nx">floor</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">random</span><span class="p">()</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">currentIndex</span><span class="p">);</span>
<span class="w">      </span><span class="nx">currentIndex</span><span class="o">--</span><span class="p">;</span>
<span class="w">  </span>
<span class="w">      </span><span class="p">[</span><span class="nx">arr</span><span class="p">[</span><span class="nx">currentIndex</span><span class="p">],</span><span class="w"> </span><span class="nx">arr</span><span class="p">[</span><span class="nx">randomIndex</span><span class="p">]]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">arr</span><span class="p">[</span><span class="nx">randomIndex</span><span class="p">],</span><span class="w"> </span><span class="nx">arr</span><span class="p">[</span><span class="nx">currentIndex</span><span class="p">]];</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">  </span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">arr</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>We won't go into the details of this, as it's a generic shuffling function, not
specific to Mental Poker, but a required piece.</p>

<p>Let's look at the two shuffling steps next. First step, in which we shuffle
and encrypt all cards with the same key:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">shuffle1</span><span class="p">(</span><span class="nx">keyProvider</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyProvider</span><span class="p">,</span><span class="w"> </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="p">[</span><span class="nx">SRAKeyPair</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="p">[]]</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">commonKey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">keyProvider</span><span class="p">.</span><span class="nx">make</span><span class="p">();</span>

<span class="w">    </span><span class="nx">deck</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">shuffleArray</span><span class="p">(</span><span class="nx">deck</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">card</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">SRA</span><span class="p">.</span><span class="nx">encryptString</span><span class="p">(</span><span class="nx">card</span><span class="p">,</span><span class="w"> </span><span class="nx">commonKey</span><span class="p">)));</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">commonKey</span><span class="p">,</span><span class="w"> </span><span class="nx">deck</span><span class="p">];</span>
<span class="p">};</span>
</pre></div>

<p>The <code>shuffle1()</code> function takes a <code>keyProvider</code>, a <code>deck</code>, and returns a
promise of a shuffled deck plus the key used to encrypt it.</p>

<p>The function is pretty straight-forward: we generate a new key, we encrypt
each card with it, then we shuffle the deck. We return the key and the now
shuffled and encrypted deck.</p>

<p>Both players need to perform the first step, after which both Alice and Bob
have encrypted the deck with \(K_A\) and \(K_B\) respectively, so neither
knows the order of the cards.</p>

<p>The next step, according to our algorithm, is for each player to decrypt the
deck with their key and encrypt each card individually with a unique key:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">shuffle2</span><span class="p">(</span><span class="nx">commonKey</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">,</span><span class="w"> </span><span class="nx">keyProvider</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyProvider</span><span class="p">,</span><span class="w"> </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="p">[</span><span class="nx">SRAKeyPair</span><span class="p">[],</span><span class="w"> </span><span class="kt">string</span><span class="p">[]]</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">privateKeys</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="nx">deck</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">deck</span><span class="p">.</span><span class="nx">map</span><span class="p">((</span><span class="nx">card</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">SRA</span><span class="p">.</span><span class="nx">decryptString</span><span class="p">(</span><span class="nx">card</span><span class="p">,</span><span class="w"> </span><span class="nx">commonKey</span><span class="p">));</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nx">deck</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">privateKeys</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">keyProvider</span><span class="p">.</span><span class="nx">make</span><span class="p">());</span>
<span class="w">        </span><span class="nx">deck</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">SRA</span><span class="p">.</span><span class="nx">encryptString</span><span class="p">(</span><span class="nx">deck</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="w"> </span><span class="nx">privateKeys</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">privateKeys</span><span class="p">,</span><span class="w"> </span><span class="nx">deck</span><span class="p">];</span>
<span class="p">}</span>
</pre></div>

<p><code>shuffle2()</code> is also fairly straight-forward. It takes the <code>commonKey</code> from
step 1, a <code>keyProvider</code>, and the encrypted <code>deck</code>.</p>

<p>First, it decrypts all cards using the <code>commonKey</code> (note the cards are still
encrypted by the other player). Next, it uses the <code>keyProvider</code> to generate
a key for each card, and encrypts each card with the key. The function returns
the private keys generated, and the re-encrypted deck.</p>

<p>We now have all the basics in place. Here's how we put it all together:</p>

<h3>Shuffling state machine</h3>

<p>Here is the state machine that describes the shuffling steps:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">makeShuffleSequence</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">ShuffleAction1</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">context</span><span class="p">.</span><span class="nx">imFirst</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">return</span><span class="p">;</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="p">[</span><span class="nx">context</span><span class="p">.</span><span class="nx">commonKey</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">shuffle1</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">keyProvider</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">);</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Shuffle1"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.clientId</span><span class="p">,</span>
<span class="w">                </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">context.deck</span><span class="p">,</span>
<span class="w">            </span><span class="p">});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleAction1</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"Shuffle1"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">deck</span><span class="p">;</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">ShuffleAction1</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">imFirst</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">return</span><span class="p">;</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="p">[</span><span class="nx">context</span><span class="p">.</span><span class="nx">commonKey</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">shuffle1</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">keyProvider</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">);</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Shuffle1"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.clientId</span><span class="p">,</span>
<span class="w">                </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">context.deck</span><span class="p">,</span>
<span class="w">            </span><span class="p">});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleAction1</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"Shuffle1"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">deck</span><span class="p">;</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">ShuffleAction2</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">context</span><span class="p">.</span><span class="nx">imFirst</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">return</span><span class="p">;</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="p">[</span><span class="nx">context</span><span class="p">.</span><span class="nx">privateKeys</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">shuffle2</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">commonKey</span><span class="o">!</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">keyProvider</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">);</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Shuffle2"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.clientId</span><span class="p">,</span>
<span class="w">                </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">context.deck</span><span class="p">,</span>
<span class="w">            </span><span class="p">});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleAction2</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"Shuffle2"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">deck</span><span class="p">;</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">ShuffleAction2</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">imFirst</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">return</span><span class="p">;</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="p">[</span><span class="nx">context</span><span class="p">.</span><span class="nx">privateKeys</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">shuffle2</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">commonKey</span><span class="o">!</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">keyProvider</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">);</span>

<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"Shuffle2"</span><span class="p">,</span>
<span class="w">                </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.clientId</span><span class="p">,</span>
<span class="w">                </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">context.deck</span><span class="p">,</span>
<span class="w">            </span><span class="p">});</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleAction2</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"Shuffle2"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>

<span class="w">            </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">deck</span><span class="p">;</span>
<span class="w">        </span><span class="p">})</span>
<span class="w">    </span><span class="p">]);</span>
<span class="p">}</span>
</pre></div>

<p>Note we are limiting this to a 2-player game, though we can easily generalize
to more players if needed.</p>

<p>This is a longer function so let's break it down:</p>

<ul>
<li>We start with a local transition: if we are not the first player (based on
some previously established turn order), we do nothing. Else we run
<code>shuffle1()</code> and post the encrypted deck as a <code>Shuffle1</code> action.</li>
<li>Next, we expect a <code>Shuffle1</code> action to arrive - either the one we just posted
(if <code>imFirst</code> is <code>true</code>) or incoming from the other player. We store the
encrypted and shuffled deck.</li>
<li>Then, we call <code>shuffle1()</code> if we are <em>not</em> the first player - if we are <em>not</em>
the first player, then it is our turn to shuffle now. We post another
<code>Shuffle1</code> action.</li>
<li>We again expect a <code>Shuffle1</code> action to arrive and update the deck.</li>
</ul>

<p>At this point, both players performed the first step of the shuffle, so the
deck is encrypted with \(K_A\) And \(K_B\) and neither players knows the turn order.
We move on to the second step of the shuffle, where each player calls
<code>shuffle2()</code> to decrypt the deck and re-encrypt each individual card. Again,
depending on whether we are first or not, we take action or wait:</p>

<ul>
<li>If <code>imFirst</code> is <code>true</code>, call <code>shuffle2()</code> and post a <code>Shuffle2</code> action.</li>
<li>Expect a <code>Shuffle2</code> action and update the deck.</li>
<li>If <code>imFirst</code> is <em>not</em> <code>true</code>, call <code>shuffle2()</code> and post a <code>Shuffle2</code> action.</li>
<li>Expect a <code>Shuffle2</code> action and update the deck.</li>
</ul>

<p>A helper function to run this state machine given an async queue:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">shuffle</span><span class="p">(</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">turnOrder</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[],</span>
<span class="w">    </span><span class="nx">sharedPrime</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span>
<span class="w">    </span><span class="nx">deck</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[],</span>
<span class="w">    </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">keySize</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">128</span><span class="w"> </span><span class="c1">// Key size, defaults to 128 bytes</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="p">[</span><span class="nx">SRAKeyPair</span><span class="p">[],</span><span class="w"> </span><span class="kt">string</span><span class="p">[]]</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">turnOrder</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Shuffle only implemented for exactly two players"</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">ShuffleContext</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span>
<span class="w">        </span><span class="nx">clientId</span><span class="p">,</span><span class="w"> </span>
<span class="w">        </span><span class="nx">deck</span><span class="p">,</span><span class="w"> </span>
<span class="w">        </span><span class="nx">imFirst</span><span class="o">:</span><span class="w"> </span><span class="kt">clientId</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">turnOrder</span><span class="p">[</span><span class="mf">0</span><span class="p">],</span>
<span class="w">        </span><span class="nx">keyProvider</span><span class="o">:</span><span class="w"> </span><span class="kt">new</span><span class="w"> </span><span class="nx">KeyProvider</span><span class="p">(</span><span class="nx">sharedPrime</span><span class="p">,</span><span class="w"> </span><span class="nx">keySize</span><span class="p">)</span>
<span class="w">    </span><span class="p">};</span>
<span class="w">    </span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">shuffleSequence</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">makeShuffleSequence</span><span class="p">();</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="nx">shuffleSequence</span><span class="p">,</span><span class="w"> </span><span class="nx">actionQueue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">context</span><span class="p">.</span><span class="nx">privateKeys</span><span class="o">!</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">deck</span><span class="p">];</span>
<span class="p">}</span>
</pre></div>

<p>We need our <code>clientId</code>, the turn order (whether we go first or not), a shared
large prime (to seed other encryption keys), an unshuffled deck, a queue, and,
optionally, a <code>keySize</code>.</p>

<p>From the input, we create a <code>ShuffleContext</code> with the required data, then we
generate the state machine by calling the function we discussed previously,
and we run the state machine using the given <code>actionQueue</code> and generated
<code>context</code>.</p>

<p>We return the private keys with which we encrypted each individual card, and
the shuffled and encrypted deck.</p>

<h3>Notes on performance</h3>

<p>Shuffling a full deck of 52 cards with large enough key sizes gets noticeably
slow. Note that we need to generate an encryption key for each card, which
involves searching for large prime numbers. The more secure we want the
encryption to be, the larger the number of bits we want in the key, the longer
it takes to find a key.</p>

<p>This can be mitigated with some loading/progress UI while shuffling. For the
<a href="https://github.com/vladris/mental-poker-toolkit/tree/main/demos/discard">demo discard game</a>
in <code>mental-poker-toolkit</code>, I used a smaller deck (only cards from <code>9</code> to <code>A</code>)
and a smaller key size (64 bits).</p>

<p>When implementing a game, it might be a good idea to start generating
encryption keys asynchronously as soon as possible - note though that the
players need to agree on a shared large prime before key generation can begin.</p>

<h2>Summary</h2>

<p>In this post we looked at an implementation of card shuffling.</p>

<ul>
<li>We recapped the shuffling algorithm for Mental Poker, which enables playing
zero-trust card games.</li>
<li>We implemented the two steps of shuffling as <code>shuffle1()</code> and <code>shuffle2()</code>.</li>
<li>We defined the state machine that models 2-player shuffling.</li>
<li>We went over a helper function that runs the state machine and outputs the
shuffled deck.</li>
<li>We briefly discussed performance of shuffling.</li>
</ul>

<p>The Mental Poker Toolkit is <a href="https://github.com/vladris/mental-poker-toolkit">here</a>.
This post covered card shuffling, which is implemented in the <code>primitives</code>
package in <a href="https://github.com/vladris/mental-poker-toolkit/blob/main/packages/primitives/src/shuffle.ts">shuffle.ts</a>.</p>
]]></description>
      <pubDate>Sun, 07 Apr 2024 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/03/22/mental-poker-part-5-state-machine.html</link>
      <guid>https://vladris.com/blog/2024/03/22/mental-poker-part-5-state-machine.html</guid>
      <title><![CDATA[Mental Poker Part 5: State Machine]]></title>
      <description><![CDATA[<h1>Mental Poker Part 5: State Machine</h1>

<p>For an overview on Mental Poker, see <a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">Mental Poker Part 0: An Overview</a>.
Other articles in this series: <a href="https://vladris.com/writings/index.html#mental-poker">https://vladris.com/writings/index.html#mental-poker</a>.
In the previous <a href="https://vladris.com/blog/2024/03/16/mental-poker-part-4-actions-and-async-queue.html">post in the series</a>
we covered <em>actions</em> and an async queue implementation.</p>

<p>In this post, we'll finally look at the infrastructure on top of which we'll
model games. The type of games we're considering can all be modeled as state
machines<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. The challenge is we need a generic enough framework that works
for any game, so let's consider what they all have in common.</p>

<h2>Transitions</h2>

<p>We can't tell what the exact states of a game are, as they depend on the
specific game. But, in general, game play implies transitioning from one
state to another.</p>

<h3>Local transitions</h3>

<p>In some cases, an action originates on our client. For example: we pick between
rock, paper, or scissors; we want to draw a card etc. This means we need to run
some logic on our client, then send an Action over our transport to other
clients.</p>

<p>To keep things generic and unopinionated, the minimal interface for this is a
function that takes an action queue and a <code>context</code>.</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">LocalTransition</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="p">,</span><span class="w"> </span><span class="nx">TContext</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>We covered the queue in the <a href="https://vladris.com/blog/2024/03/16/mental-poker-part-4-actions-and-async-queue.html">previous post</a>.
We need this in a local transition because we will run some code then, in most
cases, we'll want to enqueue an action and send it to other players. We'll look
at an example of this later on in this post.</p>

<p>The <code>context</code> can be anything - this enables the game to pass-through whatever
data the function needs. Our state machine implementation doesn't care about
what that data is, this is just the mechanism to make it available to the code
in the function.</p>

<p>The function can return either <code>void</code> or a <code>Promise&lt;void&gt;</code> in case it needs to
be async.</p>

<h3>Remote transitions</h3>

<p>In other cases, an action arrives over the transport. This is an action that
was sent either by another player, or by us and we receive it back from the
server after it has been sequenced<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>.</p>

<p>In this case, our interface is a function that takes the incoming <code>Action</code> and
a context.</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">Transition</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="p">,</span><span class="w"> </span><span class="nx">TContext</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span>
<span class="w">    </span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">TAction</span><span class="p">,</span>
<span class="w">    </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span>
<span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>In this case, we don't necessarily need access to the queue, since we won't
enqueue an action, rather we're processing one. The <code>context</code> is, again, up to
the consumer of this API.</p>

<p>The function similarly returns <code>void</code> or a <code>Promise&lt;void&gt;</code> in case it needs to
be async.</p>

<h3>Runnable transition</h3>

<p>Finally, we need an abstraction over both <code>LocalTransition</code> and <code>Transition</code> so
when we specify our state machine we can treat them the same way. We'll use
<code>RunnableTransition</code> for this:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span>
<span class="p">}</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>We expect users of our library to write code in terms of local transitions
(<code>LocalTransition</code>) and remote transitions (<code>Transition</code>). This type is meant
to be used internally. Note we are doing some type erasure here as we're going
from a generic <code>IQueue</code> to a <code>IQueue&lt;BaseAction&gt;</code>. That's because we need to
work with the queue in our library code, but the exact <code>Action</code> types depend on
the game.</p>

<p>For local transitions, we simply pass through the <code>actionQueue</code>. For remote
transitions, we dequeue an action and pass that. We'll see how to do this next.</p>

<p>We're also normalizing return to be <code>Promise&lt;void&gt;</code> regardless of whether the
transition function originally returned <code>void</code> or <code>Promise&lt;void&gt;</code>.</p>

<h2>State Machine</h2>

<p>Our state machine is implemented as a set of functions. First, we have a few
factory functions. <code>local()</code> creates a <code>RunnableTransition</code> from a
<code>LocalTransition</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">local</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="p">,</span><span class="w"> </span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">transition</span><span class="o">:</span><span class="w"> </span><span class="kt">LocalTransition</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="p">,</span><span class="w"> </span><span class="nx">TContext</span><span class="o">&gt;</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="nb">Promise</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span>
<span class="w">            </span><span class="nx">transition</span><span class="p">(</span><span class="nx">queue</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">)</span>
<span class="w">        </span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>We call <code>Promise.resolve()</code> to get a <code>Promise</code> regardless of whether the given
<code>transition</code> is a synchronous or asynchronous function.</p>

<p><code>remote()</code> converts a remote transition into a <code>RunnableTransition</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">transition</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="p">,</span><span class="w"> </span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">transition</span><span class="o">:</span><span class="w"> </span><span class="kt">Transition</span><span class="o">&lt;</span><span class="nx">TAction</span><span class="p">,</span><span class="w"> </span><span class="nx">TContext</span><span class="o">&gt;</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">action</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">queue</span><span class="p">.</span><span class="nx">dequeue</span><span class="p">();</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="nb">Promise</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">transition</span><span class="p">(</span><span class="nx">action</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">TAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">));</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>Here, we dequeue an action, then pass it to the given transition.</p>

<p>In many cases, we expect multiple players to take the same action, for example
each player picks between rock, paper, or scissors - in this case, we will
expect one remote action coming in from each player (including us), of the same
type. Most times we want to treat these actions the same way, which means we
want to run the same <code>Transition</code> function for each. The <code>repeat()</code> function
takes a <code>RunnableTransition</code> and repeats it a given number of times:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">repeat</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">transition</span><span class="o">:</span><span class="w"> </span><span class="kt">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">times</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nb">Array</span><span class="p">(</span><span class="nx">times</span><span class="p">).</span><span class="nx">fill</span><span class="p">(</span><span class="nx">transition</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>This gives as an array of <code>RunnableTransitions</code> we can execute in sequence.</p>

<p>Finally, we might want to combine the output of calling <code>local()</code> with the
output of calling <code>repeat()</code> into a longer sequence of <code>RunnableTransitions</code> we
can run - the first function gives us a <code>RunnableTransition</code>, the second
function gives us an array of <code>RunnableTransition</code>s. To address this, we
provide <code>sequence</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">sequence</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">transitions</span><span class="o">:</span><span class="w"> </span><span class="p">(</span>
<span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nx">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span>
<span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nx">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">[]</span>
<span class="w">    </span><span class="p">)[]</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">transitions</span><span class="p">.</span><span class="nx">flat</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>This function takes an array of <code>RunnableTransition</code>s, or an array of
arrays, and calls <code>flat()</code> on this to flatten nested array into a single, flat
list.</p>

<p>Once we have a sequence of transitions, we can run them using <code>run()</code>:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">run</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">sequence</span><span class="o">:</span><span class="w"> </span><span class="kt">RunnableTransition</span><span class="o">&lt;</span><span class="nx">TContext</span><span class="o">&gt;</span><span class="p">[],</span>
<span class="w">    </span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">TContext</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">transition</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">sequence</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="nx">transition</span><span class="p">(</span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>We simply execute each <code>RunnableTransition</code> in turn.</p>

<p>Understandably, this has all been abstract. Let's now see how we can use these
functions to model interactions.</p>

<h2>Interactions</h2>

<p>Let's look at a simple example: key exchange: in order to secure our transport,
we want each client to share a public key, then sign each subsequent message
with their corresponding private key.</p>

<h3>Key exchange</h3>

<p>We looked at securing the transport layer in <a href="https://vladris.com/blog/2023/11/28/mental-poker-part-3-transport.html">this post</a>.
We haven't discussed the key negotiation though.</p>

<p>Let's create the following protocol: as each client joins the game, they post
a public key. For an <code>N</code> player game, each client should expect <code>N</code> remote
transitions consisting of clients publishing public keys. Once all of these
were processed, we should have all public keys for all clients and can create
a <code>SignedTransport</code>.</p>

<p>Let's sketch out the state machine:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">makeKeyExchangeSequence</span><span class="p">(</span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">KeyExchangeAction</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">CryptoContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="c1">// Post public key ...</span>
<span class="w">        </span><span class="p">}),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">((</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyExchangeAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">CryptoContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="c1">// Store incoming public key ...</span>
<span class="w">        </span><span class="p">}),</span><span class="w"> </span><span class="nx">players</span><span class="p">)</span>
<span class="w">    </span><span class="p">]);</span>
<span class="p">}</span>
</pre></div>

<p>Note we create a <code>LocalTransition</code> in which we post our own public key, and we
repeat the remote transition handling an incoming public key (remember with
Fluid we expect the server to also send us back whatever we post).</p>

<p>Clients can join the game at different times, so we don't know in what order
the keys will come in but, luckily, each <code>Action</code> has a <code>clientId</code> so we know
who's key it is.</p>

<p>We'll look at the implementation of the transitions but first let's see what
are the <code>KeyExchangeAction</code> and <code>CryptoContext</code>:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">KeyExchangeAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"KeyExchange"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">publicKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span><span class="p">;</span>
<span class="p">};</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">CryptoContext</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="nx">me</span><span class="o">:</span><span class="w"> </span><span class="kt">PublicPrivateKeyPair</span><span class="p">;</span>
<span class="w">    </span><span class="nx">keyStore</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyStore</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p><code>KeyExchange</code> is an action consisting of <code>clientId</code> and <code>publicKey</code>, with the
<code>type</code> set to <code>"KeyExchange"</code>.</p>

<p><code>CryptoContext</code> is the context needed by the transitions implementing the key
exchange - that is we need to know our own <code>clientId</code>, our public-private
key pair, and we need a <code>keyStore</code>, which is a map of <code>clientId</code> to public key.
We looked at the <code>KeyStore</code> and the other key types in a previous blog post, but
here they are again for reference:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">Key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">PublicPrivateKeyPair</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">publicKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span><span class="p">;</span>
<span class="w">    </span><span class="nx">privateKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span><span class="p">;</span>
<span class="p">};</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">KeyStore</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Map</span><span class="o">&lt;</span><span class="nx">ClientId</span><span class="p">,</span><span class="w"> </span><span class="nx">Key</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>With these in place, let's look at the implementation of the transitions:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">makeKeyExchangeSequence</span><span class="p">(</span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span>
<span class="w">            </span><span class="k">async</span><span class="w"> </span><span class="p">(</span>
<span class="w">                </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">KeyExchangeAction</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">                </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">CryptoContext</span>
<span class="w">            </span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="c1">// Post public key</span>
<span class="w">                </span><span class="k">await</span><span class="w"> </span><span class="nx">actionQueue</span><span class="p">.</span><span class="nx">enqueue</span><span class="p">({</span>
<span class="w">                    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"KeyExchange"</span><span class="p">,</span>
<span class="w">                    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">context.clientId</span><span class="p">,</span>
<span class="w">                    </span><span class="nx">publicKey</span><span class="o">:</span><span class="w"> </span><span class="kt">context.me.publicKey</span><span class="p">,</span>
<span class="w">                </span><span class="p">});</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">        </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span>
<span class="w">            </span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span>
<span class="w">                </span><span class="p">(</span><span class="nx">action</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyExchangeAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">CryptoContext</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">                    </span><span class="c1">// This should be a KeyExchangeAction</span>
<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="s2">"KeyExchange"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid action type"</span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>

<span class="w">                    </span><span class="c1">// Protocol expects clients to post an ID</span>
<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Expected client ID"</span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>

<span class="w">                    </span><span class="c1">// Protocol expects each client to only post once and to have a unique ID</span>
<span class="w">                    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">keyStore</span><span class="p">.</span><span class="nx">has</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">                        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span>
<span class="w">                            </span><span class="s2">"Same client posted key multiple times"</span>
<span class="w">                        </span><span class="p">);</span>
<span class="w">                    </span><span class="p">}</span>

<span class="w">                    </span><span class="nx">context</span><span class="p">.</span><span class="nx">keyStore</span><span class="p">.</span><span class="nx">set</span><span class="p">(</span><span class="nx">action</span><span class="p">.</span><span class="nx">clientId</span><span class="p">,</span><span class="w"> </span><span class="nx">action</span><span class="p">.</span><span class="nx">publicKey</span><span class="p">);</span>
<span class="w">                </span><span class="p">}</span>
<span class="w">            </span><span class="p">),</span>
<span class="w">            </span><span class="nx">players</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">    </span><span class="p">]);</span>
<span class="p">}</span>
</pre></div>

<p><code>sm</code> stands for <q>state machine</q>. The functions described above live in a
<code>StateMachine</code> namespace aliased to <code>sm</code>.</p>

<p>Our local transition is simple: we enqueue a <code>KeyExchangeAction</code>, sending our
<code>clientId</code> and <code>publicKey</code> from the <code>CryptoContext</code>.</p>

<p>When a remote action comes in, we perform the required validations:</p>

<ul>
<li>Ensure it is a <code>KeyExchangeAction</code>.</li>
<li>Ensure it has a <code>clinetId</code>.</li>
<li>Ensure the same client doesn't post two different public keys.</li>
</ul>

<p>Finally, we store the <code>clientId</code> and <code>publicKey</code>.</p>

<p>The end-to-end implementation for key exchange, relying on the state machine,
is here:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeCryptoContext</span><span class="p">(</span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">CryptoContext</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">clientId</span><span class="p">,</span>
<span class="w">        </span><span class="nx">me</span><span class="o">:</span><span class="w"> </span><span class="kt">await</span><span class="w"> </span><span class="nx">Signing</span><span class="p">.</span><span class="nx">generatePublicPrivateKeyPair</span><span class="p">(),</span>
<span class="w">        </span><span class="nx">keyStore</span><span class="o">:</span><span class="w"> </span><span class="kt">new</span><span class="w"> </span><span class="nb">Map</span><span class="o">&lt;</span><span class="nx">ClientId</span><span class="p">,</span><span class="w"> </span><span class="nx">Key</span><span class="o">&gt;</span><span class="p">(),</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>

<span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">keyExchange</span><span class="p">(</span>
<span class="w">    </span><span class="nx">players</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">,</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">,</span>
<span class="w">    </span><span class="nx">actionQueue</span><span class="o">:</span><span class="w"> </span><span class="kt">IQueue</span><span class="o">&lt;</span><span class="nx">BaseAction</span><span class="o">&gt;</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">context</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">makeCryptoContext</span><span class="p">(</span><span class="nx">clientId</span><span class="p">);</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">keyExchangeSequence</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">makeKeyExchangeSequence</span><span class="p">(</span><span class="nx">players</span><span class="p">);</span>

<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">sm</span><span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="nx">keyExchangeSequence</span><span class="p">,</span><span class="w"> </span><span class="nx">actionQueue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">[</span><span class="nx">context</span><span class="p">.</span><span class="nx">me</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">.</span><span class="nx">keyStore</span><span class="p">]</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="kd">const</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p><code>makeCryptoContext()</code> is a helper function to initialize a <code>CryptoContext</code>
instance - it takes a <code>clientId</code>, generates a public-private key pair, and
initializes an empty key store.</p>

<p><code>keyExchange()</code> calls the functions we defined previously to get a
<code>CryptoContext</code>, the key exchange sequence, and calls the state machine's
<code>run()</code> to execute the key exchange.</p>

<p>Once done, it returns the client's public-private key pair, and the key store.</p>

<p>From a caller's perspective, the protocol handling key exchange is now
abstracted away behind the <code>keyExchange()</code> function. The caller doesn't have to
worry about the mechanics of exchanging keys, rather can just call this and get
back all the required data to create a <code>SignedTransport</code>.</p>

<h3>Rock-paper-scissors</h3>

<p>As a second example, we'll sketch out the state machine for a game of
rock-paper-scissors. We won't dive into all the implementation details. At a
high level, here is how we play a game of rock-paper-scissors:</p>

<ul>
<li>Each player picks from <em>rock</em>, <em>paper</em>, or <em>scissors</em>, encrypts their
selection, and posts it.</li>
<li>Once selections are posted, each player posts the key they used to encrypt.</li>
</ul>

<p>This two-step ensures players are committed to a selection and can't cheat by
observing what the other player picked and picking afterwards.</p>

<p>The state machine for this game is:</p>

<ul>
<li>A local transition in which we make our local selection.</li>
<li>Two remote transitions, getting from the server our selection and the other
player's.</li>
<li>A local transition in which we share our encryption key.</li>
<li>Two remote transitions, getting the encryption keys from the server.</li>
</ul>

<p>The state machine is:</p>
<div class="highlight"><pre><span/><span class="nx">sm</span><span class="p">.</span><span class="nx">sequence</span><span class="p">([</span>
<span class="w">    </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Post our play action</span>
<span class="w">    </span><span class="p">}),</span>
<span class="w">    </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">action</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Both player and opponent need to post their encrypted selection</span>
<span class="w">    </span><span class="p">}),</span><span class="w"> </span><span class="mf">2</span><span class="p">),</span>
<span class="w">    </span><span class="nx">sm</span><span class="p">.</span><span class="nx">local</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">queue</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Post our reveal action</span>
<span class="w">    </span><span class="p">}),</span>
<span class="w">    </span><span class="nx">sm</span><span class="p">.</span><span class="nx">repeat</span><span class="p">(</span><span class="nx">sm</span><span class="p">.</span><span class="nx">transition</span><span class="p">(</span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">reveal</span><span class="o">:</span><span class="w"> </span><span class="kt">RevealAction</span><span class="p">,</span><span class="w"> </span><span class="nx">context</span><span class="o">:</span><span class="w"> </span><span class="kt">RootStore</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Both player and opponent need to reveal their selection</span>
<span class="w">    </span><span class="p">}),</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span>
<span class="p">]);</span>
</pre></div>

<p>We won't fill in the functions in this post but this gives you an idea of how
we can model a more complex set of steps using our library.</p>

<h2>Summary</h2>

<p>In this post we looked at a state machine we can use to implement games:</p>

<ul>
<li>The state machine needs to be very unopinionated as each game implements
its own logic, defines its own <code>Action</code> types, and has its own relevant
context.</li>
<li>Local transitions are functions we initiate locally and they usually end
with an action being posted.</li>
<li>Remote transitions are functions we run in response to actions arriving
from the servers - these could've been originated by us or by another
client.</li>
<li><code>RunnableTransition</code> is a common type that can wrap local or remote
transitions.</li>
<li>We can combine transitions by repeating them, or concatenating them into
sequences. Once we have a sequence of transitions, we can run it to
implement a protocol.</li>
<li>We saw how key exchange can be implemented on top of a state machine and
sketched out the state machine for a game of rock-paper-scissors.</li>
</ul>

<p>The Mental Poker Toolkit is <a href="https://github.com/vladris/mental-poker-toolkit">here</a>.
This post covered the <a href="https://github.com/vladris/mental-poker-toolkit/tree/main/packages/state-machine">state-machine package</a>,
the key exchange is implemented in the <a href="https://github.com/vladris/mental-poker-toolkit/tree/main/packages/primitives">primitives package</a>.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p><a href="https://en.wikipedia.org/wiki/Finite-state_machine">https://en.wikipedia.org/wiki/Finite-state_machine</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p><em>Sequenced</em> is a <a href="https://fluidframework.com/">Fluid Framework</a> term.
Clients send messages to the Fluid relay service, which orders them in
the order they came in and broadcasts them to all clients. This is to
ensure all clients eventually see all the messages sent <em>in the same
order</em>. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Fri, 22 Mar 2024 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/03/16/mental-poker-part-4-actions-and-async-queue.html</link>
      <guid>https://vladris.com/blog/2024/03/16/mental-poker-part-4-actions-and-async-queue.html</guid>
      <title><![CDATA[Mental Poker Part 4: Actions and Async Queue]]></title>
      <description><![CDATA[<h1>Mental Poker Part 4: Actions and Async Queue</h1>

<p>For an overview on Mental Poker, see <a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">Mental Poker Part 0: An Overview</a>.
Other articles in this series: <a href="https://vladris.com/writings/index.html#mental-poker">https://vladris.com/writings/index.html#mental-poker</a>.
In the previous <a href="https://vladris.com/blog/2023/11/28/mental-poker-part-3-transport.html">post in the series</a>
we covered the transport.</p>

<p>As I was building up the library and looking at state machines that would run
turns in a game, I realized an async queue would come in handy. The challenge
with the raw <code>ITransport</code> interface built on top of the Fluid ledger is that if
you are not the first client to join a session, you end up with a set of ops
that already exist on the ledger. You need a way to consume both the ops that
were already sequenced and new incoming ops. An async interface is also easier
to consume than callbacks.</p>

<p>Before diving into that though, letâs talk about actions.</p>

<h2>Actions</h2>

<p>As a reminder, <em>op</em> is the Fluid Framework term for data being sent/received. In
Mental Poker we use <em>actions</em>. All actions should be subtypes of <code>BaseAction</code>:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">ClientId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>

<span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">BaseAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="nx">unknown</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Every action should have a <code>clientId</code> showing which client it came from, and a
<code>type</code>.</p>

<p>For example, hereâs how we would model a game of Rock/Paper/Scissors:</p>

<ul>
<li>Both players pick <em>rock</em> or <em>paper</em> or <em>scissors</em>, encrypt their selection,
and post it on the ledger.</li>
<li>Next, both players post their encryption key, so the other player can decrypt
and see the selection.</li>
</ul>

<p>We model the game in these two steps so regardless of which player moves first,
the player choices are revealed after they have been put on the ledger. If a
player would simply post their unencrypted selection, the other player might
cheat by looking at it before posting their own.</p>

<p>I will cover the Rock/Paper/Scissors implementation in detail in a future post,
for now, letâs just go over the actions:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">PlayAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"PlayAction"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">encryptedSelection</span><span class="o">:</span><span class="w"> </span><span class="kt">EncryptedSelection</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">RevealAction</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"RevealAction"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">key</span><span class="o">:</span><span class="w"> </span><span class="kt">SerializedSRAKeyPair</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">Action</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">PlayAction</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">RevealAction</span><span class="p">;</span>
</pre></div>

<p>The two actions described above are modeled as <code>PlayAction</code> and <code>RevealAction</code>.
Both of these have a <code>clientId</code> and <code>type</code>, thus are subtypes of <code>BaseAction</code>.
Finally, the <code>Action</code> type represents all possible actions in the game.</p>

<p>This becomes relevant as we move higher in the stack of the Mental Poker
library. Once we start encoding some of the game semantics, we require generic
types to extend <code>BaseAction</code>. This is what happens with the async queue.</p>

<h2>Async queue</h2>

<p>As I mentioned at the beginning of the article, queues aim to provide a nicer
API over the transport. The interface is very simple:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">interface</span><span class="w"> </span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">T</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">enqueue</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="nx">dequeue</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>For any type <code>T</code> extending <code>BaseAction</code>, we can <code>enqueue()</code>  a value and we can
<code>dequeue()</code> a value. Both of the operations are asynchronous.</p>

<p>Iâll show the full implementation then go over the details:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nx">ActionQueue</span><span class="o">&lt;</span><span class="nx">T</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">BaseAction</span><span class="o">&gt;</span><span class="w"> </span><span class="k">implements</span><span class="w"> </span><span class="nx">IQueue</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">queue</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span>
<span class="w">        </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">transport</span><span class="o">:</span><span class="w"> </span><span class="kt">ITransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="nx">preseed</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span>
<span class="w">    </span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">transport</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">queue</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="p">});</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">preseed</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">transport</span><span class="p">.</span><span class="nx">getActions</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">this</span><span class="p">.</span><span class="nx">queue</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">async</span><span class="w"> </span><span class="nx">enqueue</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">transport</span><span class="p">.</span><span class="nx">postAction</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">async</span><span class="w"> </span><span class="nx">dequeue</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">queue</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">result</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="nb">Promise</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">((</span><span class="nx">resolve</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">transport</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="nx">resolve</span><span class="p">(</span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">dequeue</span><span class="p">());</span>
<span class="w">            </span><span class="p">});</span>
<span class="w">        </span><span class="p">});</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>The implementation maintains an array of <code>T</code>s (actions). The constructor takes a
<code>transport</code> argument of type <code>ITransport</code> and <code>preseed</code> flag:</p>
<div class="highlight"><pre><span/><span class="kr">constructor</span><span class="p">(</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">transport</span><span class="o">:</span><span class="w"> </span><span class="kt">ITransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">preseed</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">transport</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">queue</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">    </span><span class="p">});</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">preseed</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">transport</span><span class="p">.</span><span class="nx">getActions</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">queue</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="cm">/* ... */</span>
</pre></div>

<p>The queue starts listening to the <code>actionPosted</code> event and whenever we have an
incoming value, we push it to the internal queue. If <code>preseed</code> is <code>true</code>, we
also push all actions already posted to the queue.</p>

<p>The reason we make this optional is that we might end up using multiple queues
in a game implementation but we only want to consume the actions posted on the
ledger before we joined the session once. After we are âup to speedâ, new
incoming actions fire events which we can consume in realtime. So we would
usually create our first queue with <code>preseed</code> set to <code>true</code> and subsequent
queues with <code>preseed</code> set to <code>false</code>.</p>

<p>Enqueuing a value is trivial - we leverage the transportâs <code>postAction</code> API:</p>
<div class="highlight"><pre><span/><span class="cm">/* ... */</span>

<span class="k">async</span><span class="w"> </span><span class="nx">enqueue</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">transport</span><span class="p">.</span><span class="nx">postAction</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>

<span class="cm">/* ... */</span>
</pre></div>

<p>Dequeuing is a bit more interesting:</p>
<div class="highlight"><pre><span/><span class="cm">/* ... */</span>

<span class="k">async</span><span class="w"> </span><span class="nx">dequeue</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">queue</span><span class="p">.</span><span class="nx">shift</span><span class="p">();</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">result</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nb">Promise</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">((</span><span class="nx">resolve</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">transport</span><span class="p">.</span><span class="nx">once</span><span class="p">(</span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">resolve</span><span class="p">(</span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">dequeue</span><span class="p">());</span>
<span class="w">        </span><span class="p">});</span>
<span class="w">    </span><span class="p">});</span>
<span class="p">}</span>

<span class="cm">/* ... */</span>
</pre></div>

<p>First, we call <code>shift()</code> on the queue. This either returns a value or
<code>undefined</code> if the queue is empty.</p>

<p>If we do get a value, we return a resolved promise right away.</p>

<p>If we donât have a value, we add a one-time listener to the <code>actionPosted</code>
event. When a new action is posted, the underlying transport will fire the
event. Since event listeners are called in the order they subscribed, we are
guaranteed the listener we added in the constructor fires first, and adds the
value to <code>queue</code>. We resolve the promise by recursively calling <code>dequeue()</code> and
awaiting the response.</p>

<p>The reason we do this is we might have multiple callers to <code>dequeue()</code> holding
on to promises. In this case, we donât want to resolve all of them with the
incoming value, rather just the first one. The first recursive call to
<code>dequeue()</code> should grab the value from the internal <code>queue</code> and return it right
away, while other recursive callers would end up awaiting again until a new
value comes in. There's probably a more efficient non-recursive implementation
but for our specific use-case (games), we don't expect many cases where we have
multiple dequeus pending.</p>

<h2>Using the queue</h2>

<p>There are two main reasons for using this queue rather than relying directly on
the underlying transport.</p>

<p>First, the underlying transport can have a set of actions (messages) that
already arrived on the client (which we would retrieve with the <code>getActions()</code>
method), and some which arrive in real time (which would fire events). The
queue gives us a unified way to consume both, by calling <code>await dequeue()</code>.</p>

<p>Besides a unified interface, we expect multiple spots in the code to wait for
an incoming action. This depends on the game implementation, but usually at
different game states we expect different messages to come in. This is harder
to achieve waiting for event callbacks and much easier to do via the same
<code>await dequeue()</code> call.</p>

<h2>Summary</h2>

<p>In this post we looked at <em>actions</em>, the key building blocks of Mental Poker
games, and an async queue which provides a clean abstraction over the underlying
transport.</p>

<p>The code covered in this post is available on GitHub in
theÂ <strong><a href="https://github.com/vladris/mental-poker-toolkit/">mental-poker-toolkitÂ repo</a></strong>.
<code>BaseAction</code> and the <code>ITransport</code> and <code>IQueue</code> interfaces are part of the core
types package <strong><a href="https://github.com/vladris/mental-poker-toolkit/tree/main/packages/types">packages/types</a></strong>.
<code>ActionQueue</code>Â is implemented underÂ <strong><a href="https://github.com/vladris/mental-poker-toolkit/tree/main/packages/action-queue">packages/action-queue</a></strong>.</p>
]]></description>
      <pubDate>Sat, 16 Mar 2024 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2024/01/10/notes-on-advent-of-code-2023.html</link>
      <guid>https://vladris.com/blog/2024/01/10/notes-on-advent-of-code-2023.html</guid>
      <title><![CDATA[Notes on Advent of Code 2023]]></title>
      <description><![CDATA[<h1>Notes on Advent of Code 2023</h1>

<p>I always have fun with <a href="https://adventofcode.com">Advent of Code</a> every
December, and last year I did write <a href="https://vladris.com/blog/2023/01/07/notes-on-advent-of-code-2022.html">a blog post</a>
covering some of the more interesting problems I worked through. I'll continue
the tradition this year.</p>

<p>I'll repeat my disclaimer from last time:</p>

<blockquote>
<p><strong>Disclaimer on my solutions</strong></p>

<p>I use Python because I find it easiest for this type of coding. I treat
solving these as a write-only exercise. I do it for the problem-solving bit,
so I don't comment the code &amp; once I find the solution I consider it <q>done</q> -
I don't revisit and try to optimize even though sometimes I strongly feel
like there is a better solution. I don't even share code between part 1 and
part 2 - once part 1 is solved, I copy/paste the solution and change it to
solve part 2, so each can be run independently. I also rarely use libraries,
and when I do it's some standard ones like <code>re</code>, <code>itertools</code>, or <code>math</code>. The
code has no comments and is littered with magic numbers and strange variable
names. This is not how I usually code, rather my decadent holiday indulgence.
I wasn't thinking I will end up writing a blog post discussing my solutions so
I would like to apologize for the code being hard to read.</p>
</blockquote>

<p>All my solutions are on my GitHubÂ <strong><a href="https://github.com/vladris/aoc">here</a></strong>.</p>

<p>This time around, I did use GitHub Copilot, with mixed results. In general, it
mostly helped with tedious work, like implementing the same thing to work in
different directions - there are problems that require we do something while
heading north, then same thing while heading east etc. I did also observe it
produce buggy code that I had to manually edit.</p>

<p>I'll skip over the first few days as they tend to be very easy.</p>

<h2>Day 9</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/9">here</a>.</p>

<p>This is an easy problem, I just want to call out a shortcut: for part 2, to
exact same algorithm as in part 1 works if you first reverse the input. This was
a neat discovery that saved me a bunch of work.</p>

<h2>Day 10</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/10">here</a>.</p>

<p>Part 1 was again very straightforward. I found part 2 a bit more interesting,
especially the fact that we can determine whether a tile is <q>inside</q> or
<q>outside</q> our loop by only looking at a single row (or column). We always start
<q>outside</q>, then scan each tile. If we hit a <code>|</code>, then we toggle from <q>outside</q>
to <q>inside</q> and vice-versa. If we hit an <code>L</code> or a <code>F</code>, we continue while we're
on a <code>-</code> (these are all parts of our loop), and we stop on the <code>7</code> or <code>J</code>. If we
started on <code>L</code> and ended on <code>J</code> or started on <code>F</code> and eded on <code>7</code> - meaning the
pipe bends and turns back the way we came, we don't change our state. On the
other hand, if the pipe goes <q>down</q> from <code>L</code> to <code>7</code> or <q>up</q> from <code>F</code> to <code>J</code>,
then we toggle <q>outside</q>/<q>inside</q>. For each non-pipe tile, if we're <q>inside</q>, we
count it. Maybe this is obvious but it took me a bit to figure it out.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">scan_line</span><span class="p">(</span><span class="n">ln</span><span class="p">):</span>
    <span class="n">total</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">inside</span><span class="p">,</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="kc">False</span><span class="p">,</span> <span class="kc">None</span>
    <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">ln</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">inside</span><span class="p">:</span>
                <span class="n">total</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">ln</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'|'</span><span class="p">:</span>
                <span class="n">inside</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">inside</span>
                <span class="k">continue</span>
            
            <span class="c1"># grid[ln][i] in 'LF'</span>
            <span class="n">start</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="n">ln</span><span class="p">][</span><span class="n">i</span><span class="p">]</span>
            <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="k">while</span> <span class="n">grid</span><span class="p">[</span><span class="n">ln</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'-'</span><span class="p">:</span>
                <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>

            <span class="k">if</span> <span class="n">start</span> <span class="o">==</span> <span class="s1">'L'</span> <span class="ow">and</span> <span class="n">grid</span><span class="p">[</span><span class="n">ln</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'7'</span> <span class="ow">or</span> \
               <span class="n">start</span> <span class="o">==</span> <span class="s1">'F'</span> <span class="ow">and</span> <span class="n">grid</span><span class="p">[</span><span class="n">ln</span><span class="p">][</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'J'</span><span class="p">:</span>
               <span class="n">inside</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">inside</span>
    <span class="k">return</span> <span class="n">total</span>
</pre></div>

<p>In the code above, <code>visited</code> tracks pipe segments (as opposed to tiles that are
not part of the pipe).</p>

<h2>Day 11</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/11">here</a>.</p>

<p>Day 11 was easy, so not much to discuss. Use Manhattan distance for part 1 and
in part 2, just add <code>999999</code> for every row or column crossed that doesn't
contain any galaxies.</p>

<h2>Day 12</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/12">here</a>.</p>

<p>Part 1 was very easy.</p>

<p>Part 2 was a bit harder because just trying out every combination takes forever
to run. I initially tried to do something more clever around deciding when to
turn a <code>?</code> into <code>#</code> or <code>.</code> depending on what's around it, where we are in the
sequence, etc. But ultimately it turns out just adding memoization made the
combinatorial approach run very fast.</p>

<h2>Day 13</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/13">here</a>.</p>

<p>This was a very easy one, so I won't cover it.</p>

<h2>Day 14</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/14">here</a>.</p>

<p>This was easy but part 2 was tedious, having to implement <code>tilt</code> functions for
various directions. This is where Copilot saved me a bunch of typing.</p>

<p>Once we have the <code>tilt</code> functions, we can implement a <code>cycle</code> function that
tilts things north, then west, then south, then east. Finally, we need a bit of
math to figure out the final position: we save the state of the grid after each
cycle and as soon as we find a configuration we encountered before, it means we
found our cycle. Based on this, we know how many steps we have before the cycle,
what the length of the cycle is, so we can compute the state after 1000000000
cycles:</p>
<div class="highlight"><pre><span/><span class="n">pos</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">while</span> <span class="p">(</span><span class="n">state</span> <span class="o">:=</span> <span class="n">cycle</span><span class="p">())</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">pos</span><span class="p">:</span>
    <span class="n">pos</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>

<span class="n">lead</span><span class="p">,</span> <span class="n">loop</span> <span class="o">=</span> <span class="n">pos</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">state</span><span class="p">),</span> <span class="nb">len</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span> <span class="o">-</span> <span class="n">pos</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">state</span><span class="p">)</span>
<span class="n">d</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1000000000</span> <span class="o">-</span> <span class="n">lead</span><span class="p">)</span> <span class="o">%</span> <span class="n">loop</span>
</pre></div>

<p>With this, we need to count the load of the north support beams for the grid we
have at <code>pos[lead + d - 1]</code>.</p>

<h2>Day 15</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/15">here</a>.</p>

<p>Another very easy one that I won't cover.</p>

<h2>Day 16</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/16">here</a>.</p>

<p>This one was also easy and tedious, as we have to handle the different types of
reflections. Another one where Copilot saved me a lot of typing.</p>

<h2>Day 17</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/17">here</a>.</p>

<h3>Part 1</h3>

<p>This was a fairly straightforward depth-first search, where we keep a cache of
how much heat loss we have up to a certain point. The one interesting
complication is that we can only move forward 3 times. In the original
implementation, I keyed the cache on grid coordinates + direction we're going
in + how many steps we already took in that direction. This worked in
reasonable time.</p>

<h3>Part 2</h3>

<p>In part 2, we now have to move at least 4 steps in one direction and at
most 10. The cache I used in part 1 doesn't work that well anymore. On the
other hand, I realized that rather than keeping track of direction and how
many steps we took in that direction so far, I can model this differently: we
are moving either horizontally or vertically. If we're at some point and moving
horizontally, we can expand our search to all destination points (from 4 to 10
away horizontally or vertically) and flip the direction. For example, if we
just moved horizontally to the right, we won't move further to the right as we
already covered all those cases, and we won't move back left as the crucible
can't turn 180 degrees. That means the only possible directions we can take are
up or down in this case, meaning since we just moved horizontally, we now have
to move vertically.</p>

<p>This makes our cache much smaller: our key is the coordinates of the cell and
the direction we were moving in. This also makes the depth-first search
complete very fast.</p>
<div class="highlight"><pre><span/><span class="n">best</span><span class="p">,</span> <span class="n">end</span> <span class="o">=</span> <span class="p">{},</span> <span class="mi">1000000</span>

<span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="n">p</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">end</span>

    <span class="k">if</span> <span class="n">p</span> <span class="o">&gt;=</span> <span class="n">end</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">y</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">p</span> <span class="o">&lt;</span> <span class="n">end</span><span class="p">:</span>
            <span class="n">end</span> <span class="o">=</span> <span class="n">p</span>
        <span class="k">return</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span> <span class="ow">in</span> <span class="n">best</span> <span class="ow">and</span> <span class="n">best</span><span class="p">[(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">)]</span> <span class="o">&lt;=</span> <span class="n">p</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="n">best</span><span class="p">[(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">)]</span> <span class="o">=</span> <span class="n">p</span>
    
    <span class="k">if</span> <span class="n">d</span> <span class="o">!=</span> <span class="s1">'H'</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">x</span> <span class="o">+</span> <span class="mi">3</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">]):</span>
            <span class="n">pxr</span> <span class="o">=</span> <span class="n">p</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">+</span> <span class="mi">2</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">+</span> <span class="mi">3</span><span class="p">][</span><span class="n">y</span><span class="p">]</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">11</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">x</span> <span class="o">+</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">):</span>
                    <span class="n">pxr</span> <span class="o">+=</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">+</span> <span class="n">i</span><span class="p">][</span><span class="n">y</span><span class="p">]</span>
                    <span class="n">search</span><span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">i</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="s1">'H'</span><span class="p">,</span> <span class="n">pxr</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">x</span> <span class="o">-</span> <span class="mi">3</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">pxl</span> <span class="o">=</span> <span class="n">p</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">-</span> <span class="mi">2</span><span class="p">][</span><span class="n">y</span><span class="p">]</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">-</span> <span class="mi">3</span><span class="p">][</span><span class="n">y</span><span class="p">]</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">11</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">x</span> <span class="o">-</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">pxl</span> <span class="o">+=</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">-</span> <span class="n">i</span><span class="p">][</span><span class="n">y</span><span class="p">]</span>
                    <span class="n">search</span><span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="n">i</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="s1">'H'</span><span class="p">,</span> <span class="n">pxl</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">d</span> <span class="o">!=</span> <span class="s1">'V'</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">3</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
            <span class="n">pyd</span> <span class="o">=</span> <span class="n">p</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">11</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">y</span> <span class="o">+</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
                    <span class="n">pyd</span> <span class="o">+=</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span> <span class="o">+</span> <span class="n">i</span><span class="p">]</span>
                    <span class="n">search</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="n">i</span><span class="p">,</span> <span class="s1">'V'</span><span class="p">,</span> <span class="n">pyd</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">y</span> <span class="o">-</span> <span class="mi">3</span> <span class="o">&gt;-</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">pyu</span> <span class="o">=</span> <span class="n">p</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span> <span class="o">-</span> <span class="mi">2</span><span class="p">]</span> <span class="o">+</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span> <span class="o">-</span> <span class="mi">3</span><span class="p">]</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">11</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">y</span> <span class="o">-</span> <span class="n">i</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">pyu</span> <span class="o">+=</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span><span class="p">][</span><span class="n">y</span> <span class="o">-</span> <span class="n">i</span><span class="p">]</span>
                    <span class="n">search</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">-</span> <span class="n">i</span><span class="p">,</span> <span class="s1">'V'</span><span class="p">,</span> <span class="n">pyu</span><span class="p">)</span>
</pre></div>

<p>I realized this approach actually applies well to part 1 too, and retrofitted it
there. The only difference is instead of expanding to the cells +4 to +10 in a
direction, we expand to the cells +1 to +3.</p>

<h2>Day 18</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/18">here</a>.</p>

<h3>Part 1</h3>

<p>The first part is easy - we plot the input on a grid, then flood fill to find
the area.</p>

<p>In the below code, <code>dig</code> is the input, processed as a tuple of direction and
number of steps:</p>
<div class="highlight"><pre><span/><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">grid</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">{(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)}</span>
<span class="k">for</span> <span class="n">dig</span> <span class="ow">in</span> <span class="n">digs</span><span class="p">:</span>
    <span class="k">match</span> <span class="n">dig</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
        <span class="k">case</span> <span class="s1">'U'</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="n">y</span> <span class="o">-=</span> <span class="mi">1</span>
                <span class="n">grid</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
        <span class="k">case</span> <span class="s1">'R'</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="n">x</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="n">grid</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
        <span class="k">case</span> <span class="s1">'D'</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="n">y</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="n">grid</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
        <span class="k">case</span> <span class="s1">'L'</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="n">x</span> <span class="o">-=</span> <span class="mi">1</span>
                <span class="n">grid</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>

<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="nb">min</span><span class="p">([</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">grid</span><span class="p">]),</span> <span class="nb">min</span><span class="p">([</span><span class="n">y</span> <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">grid</span><span class="p">])</span>
<span class="k">while</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">grid</span><span class="p">:</span>
    <span class="n">y</span> <span class="o">+=</span> <span class="mi">1</span>

<span class="n">queue</span> <span class="o">=</span> <span class="p">[(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)]</span>
<span class="k">while</span> <span class="n">queue</span><span class="p">:</span>
    <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="ow">in</span> <span class="n">grid</span><span class="p">:</span>
        <span class="k">continue</span>

    <span class="n">grid</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
    <span class="n">queue</span> <span class="o">+=</span> <span class="p">[(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="p">(</span><span class="n">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">),</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)]</span>

<span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
</pre></div>

<h3>Part 2</h3>

<p>Part 2 is trickier, as the number are way larger and the same flood fill
algorithm won't work. My approach was to divide the area into rectangles: as we
process all movements, we end up with a set of <code>(x, y)</code> tuples of points where
our line changes direction. If we sort all the <code>x</code> coordinates and all <code>y</code>
coordinates independently, we end up with a grid where we can treat each pair of
subsequent <code>x</code>s and <code>y</code>s as describing a rectangle on our grid.</p>
<div class="highlight"><pre><span/><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">points</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)]</span>
<span class="k">for</span> <span class="n">dig</span> <span class="ow">in</span> <span class="n">digs</span><span class="p">:</span>
    <span class="k">match</span> <span class="n">dig</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
        <span class="k">case</span> <span class="mi">0</span><span class="p">:</span> <span class="n">x</span> <span class="o">+=</span> <span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="k">case</span> <span class="mi">1</span><span class="p">:</span> <span class="n">y</span> <span class="o">+=</span> <span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="k">case</span> <span class="mi">2</span><span class="p">:</span> <span class="n">x</span> <span class="o">-=</span> <span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="k">case</span> <span class="mi">3</span><span class="p">:</span> <span class="n">y</span> <span class="o">-=</span> <span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>

    <span class="k">if</span> <span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">:</span>
        <span class="nb">print</span><span class="p">(</span><span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
    <span class="n">points</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>

<span class="n">xs</span><span class="p">,</span> <span class="n">ys</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">({</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">points</span><span class="p">}),</span> <span class="nb">sorted</span><span class="p">({</span><span class="n">y</span> <span class="k">for</span> <span class="n">_</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">points</span><span class="p">})</span>
</pre></div>

<p>Where <code>digs</code> above represents the input, processed as before into direction and
number of steps tuples.</p>

<p>Now <code>points</code> contains all the connected points we get following the directions,
which means a pair of subsequent points describes a line. Once we have this, we
can start a flood fill in one of the rectangles and proceed as follows: if there
is a north boundary, meaning we have a line between our top left and top right
coordinates, then we don't recurse north; otherwise we go to the rectangle north
of our current rectangle and repeat the algorithm there. Same for east, south,
west.</p>

<p>Since we have to consider each point in the terrain in our area calculation, we
need to be careful how we measure the boundaries of each rectangle so we don't
double-count or omit points. To ensure this, my approach was that for each
rectangle we count, we count an extra line north (if there is no boundary) and
an extra line east (if there is no boundary). If there's neither a north nor an
east boundary, then we add 1 for the north-east corner. This should ensure we
don't double-count, as each rectangle only considers its north and east
boundaries, and we don't miss anything, as any rectangle without a boundary will
count the additional points. What remains is the perimeter of our surface, which
we add it at the end. The explanations might sound convoluted, but the code is
very easy to understand:</p>
<div class="highlight"><pre><span/><span class="n">queue</span><span class="p">,</span> <span class="n">total</span><span class="p">,</span> <span class="n">visited</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)],</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">while</span> <span class="n">queue</span><span class="p">:</span>
    <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

    <span class="n">e</span> <span class="o">=</span> <span class="nb">min</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">xs</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">x</span><span class="p">])</span>
    <span class="n">s</span> <span class="o">=</span> <span class="nb">max</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">ys</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">y</span><span class="p">])</span>
    <span class="n">w</span> <span class="o">=</span> <span class="nb">max</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">xs</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">x</span><span class="p">])</span>
    <span class="n">n</span> <span class="o">=</span> <span class="nb">min</span><span class="p">([</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">ys</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="n">y</span><span class="p">])</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="n">e</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
        <span class="k">continue</span>
    <span class="n">visited</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">n</span><span class="p">,</span> <span class="n">e</span><span class="p">))</span>

    <span class="n">total</span> <span class="o">+=</span> <span class="p">(</span><span class="n">e</span> <span class="o">-</span> <span class="n">w</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="n">s</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>

    <span class="n">found_n</span><span class="p">,</span> <span class="n">found_s</span><span class="p">,</span> <span class="n">found_e</span><span class="p">,</span> <span class="n">found_w</span> <span class="o">=</span> <span class="kc">False</span><span class="p">,</span> <span class="kc">False</span><span class="p">,</span> <span class="kc">False</span><span class="p">,</span> <span class="kc">False</span>
    <span class="k">for</span> <span class="n">l1</span><span class="p">,</span> <span class="n">l2</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">points</span><span class="p">,</span> <span class="n">points</span><span class="p">[</span><span class="mi">1</span><span class="p">:]):</span>
        <span class="k">if</span> <span class="n">l1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">l2</span><span class="p">[</span><span class="mi">1</span><span class="p">]:</span>
            <span class="k">if</span> <span class="n">l1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">n</span> <span class="ow">and</span> <span class="p">(</span><span class="n">l1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">l2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">or</span> <span class="n">l2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">l1</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
                <span class="n">found_n</span> <span class="o">=</span> <span class="kc">True</span>
            <span class="k">if</span> <span class="n">l1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">s</span> <span class="ow">and</span> <span class="p">(</span><span class="n">l1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">l2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">or</span> <span class="n">l2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">x</span> <span class="o">&lt;</span> <span class="n">l1</span><span class="p">[</span><span class="mi">0</span><span class="p">]):</span>
                <span class="n">found_s</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="k">elif</span> <span class="n">l1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">l2</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
            <span class="k">if</span> <span class="n">l1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">e</span> <span class="ow">and</span> <span class="p">(</span><span class="n">l1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">l2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">or</span> <span class="n">l2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">l1</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="n">found_e</span> <span class="o">=</span> <span class="kc">True</span>
            <span class="k">if</span> <span class="n">l1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">w</span> <span class="ow">and</span> <span class="p">(</span><span class="n">l1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">l2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">or</span> <span class="n">l2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">y</span> <span class="o">&lt;</span> <span class="n">l1</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="n">found_w</span> <span class="o">=</span> <span class="kc">True</span>
                
    <span class="k">if</span> <span class="ow">not</span> <span class="n">found_n</span><span class="p">:</span>
        <span class="n">total</span> <span class="o">+=</span> <span class="n">e</span> <span class="o">-</span> <span class="n">w</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">found_s</span><span class="p">:</span>
        <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">s</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">found_e</span><span class="p">:</span>
        <span class="n">total</span> <span class="o">+=</span> <span class="n">n</span> <span class="o">-</span> <span class="n">s</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">e</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">found_w</span><span class="p">:</span>
        <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">w</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="n">found_n</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">found_e</span><span class="p">:</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">e</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">points</span><span class="p">:</span>
            <span class="n">total</span> <span class="o">+=</span> <span class="mi">1</span>

<span class="n">total</span> <span class="o">+=</span> <span class="nb">sum</span><span class="p">([</span><span class="n">dig</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">for</span> <span class="n">dig</span> <span class="ow">in</span> <span class="n">digs</span><span class="p">])</span>
</pre></div>

<h2>Day 19</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/19">here</a>.</p>

<h3>Part 1</h3>

<p>For the first part, we can process rule by rule.</p>

<h3>Part 2</h3>

<p>For the second part, start with bounds: <code>(1, 4000)</code> for all of <code>xmas</code>. Then at
each decision point, recurse updating bounds. Whenever we hit an <code>A</code>, add the
bounds to the list of accepted bounds.</p>

<p>Bounds are guaranteed to never overlap, by definition.</p>
<div class="highlight"><pre><span/><span class="n">accepts</span> <span class="o">=</span> <span class="p">[]</span>

<span class="k">def</span><span class="w"> </span><span class="nf">execute_workflow</span><span class="p">(</span><span class="n">workflow_key</span><span class="p">,</span> <span class="n">bounds</span><span class="p">):</span>
    <span class="n">workflow</span> <span class="o">=</span> <span class="n">workflows</span><span class="p">[</span><span class="n">workflow_key</span><span class="p">]</span>
    <span class="k">for</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">workflow</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">rule</span> <span class="o">==</span> <span class="s1">'A'</span><span class="p">:</span>
            <span class="n">accepts</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">bounds</span><span class="p">)</span>
            <span class="k">return</span>
        <span class="k">if</span> <span class="n">rule</span> <span class="o">==</span> <span class="s1">'R'</span><span class="p">:</span>
            <span class="k">return</span>
        <span class="k">if</span> <span class="n">rule</span> <span class="ow">in</span> <span class="n">workflows</span><span class="p">:</span>
            <span class="n">execute_workflow</span><span class="p">(</span><span class="n">rule</span><span class="p">,</span> <span class="n">bounds</span><span class="p">)</span>
            <span class="k">return</span>

        <span class="n">check</span><span class="p">,</span> <span class="n">next_workflow</span> <span class="o">=</span> <span class="n">rule</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">':'</span><span class="p">)</span>
        <span class="k">if</span> <span class="s1">'&lt;'</span> <span class="ow">in</span> <span class="n">check</span><span class="p">:</span>
            <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="o">=</span> <span class="n">check</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'&lt;'</span><span class="p">)</span>
            <span class="n">nb</span> <span class="o">=</span> <span class="n">bounds</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
            <span class="n">nb</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">nb</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="nb">int</span><span class="p">(</span><span class="n">val</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
            <span class="n">bounds</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">bounds</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span>
        <span class="k">elif</span> <span class="s1">'&gt;'</span> <span class="ow">in</span> <span class="n">check</span><span class="p">:</span>
            <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="o">=</span> <span class="n">check</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'&gt;'</span><span class="p">)</span>
            <span class="n">nb</span> <span class="o">=</span> <span class="n">bounds</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
            <span class="n">nb</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">val</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nb</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span>
            <span class="n">bounds</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">bounds</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="nb">int</span><span class="p">(</span><span class="n">val</span><span class="p">))</span>

        <span class="n">execute_workflow</span><span class="p">(</span><span class="n">next_workflow</span><span class="p">,</span> <span class="n">nb</span><span class="p">)</span>

<span class="n">execute_workflow</span><span class="p">(</span><span class="s1">'in'</span><span class="p">,</span> <span class="p">{</span><span class="s1">'x'</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4000</span><span class="p">),</span> <span class="s1">'m'</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4000</span><span class="p">),</span> <span class="s1">'a'</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4000</span><span class="p">),</span> <span class="s1">'s'</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4000</span><span class="p">)})</span>
</pre></div>

<p>This gives us all accepted ranges for each of <code>x</code>, <code>m</code>, <code>a</code>, and <code>s</code>.</p>

<h2>Day 20</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/20">here</a>.</p>

<h3>Part 1</h3>

<p>For the first part, we can model the various module types as classes with a
common interface and different implementations. Since one of the requirements is
to process pulses in the order they are sent, we will use a queue rather than
have objects call each other based on connections. So rather than module <code>A</code>
directly calling connected module <code>B</code> when it receives a signal (which would
cause out-of-order processing), model <code>A</code> will just queue a signal for module
<code>B</code>, which will be processed once the signals queued before this one are already
processed.</p>

<p>I won't share the code here as it is straightforward. You can find it on my
GitHub.</p>

<h3>Part 2</h3>

<p>This one was one of the most interesting problems this year. Simply simulating
button presses wouldn't work. I ended up dumping the diagram as a dependency
graph and it looks like the only module that signals <code>rx</code> is a conjunction
module with multiple inputs.</p>

<p>Conjunction modules emit a low pulse when they remember high pulses being sent
by all their connected inputs. In this case, we can simulate button presses and
keep track when each input to this conjunction module emits a high pulse. Then
we compute the least common multiple of these to determine when the <code>rx</code> module
will get a low signal.</p>

<p>My full solution is
<a href="https://github.com/vladris/aoc/blob/master/2023/20/02.py">here</a>, though I'm
still pretty sure it is topology-dependent. Meaning we might have a different
set up where the inputs to this conjunction model are not fully independent,
which might make LCM not return the correct answer.</p>

<h2>Day 21</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/21">here</a>.</p>

<h3>Part 1</h3>

<p>Part 1 is trivial, we can easily simulate 64 steps and count reachable spots.</p>

<h3>Part 2</h3>

<p>The second part is much more tricky - this is actually the problem I spent the
most time on. Since the garden is infinite, and we are looking for a very high
number of steps, we can't use the same approach as in part 1 to simply simulate
moves.</p>

<p>Let's now call a <q>tile</q> a repetition of the garden on our infinite grid. Say we
start with the garden at <code>(0, 0)</code>. Then as we expand beyond its bounds, we reach
tiles <code>(-1, 0)</code>, <code>(1, 0)</code>, <code>(0, -1)</code>, <code>(0, 1)</code>, which are repetitions of our
initial garden.</p>

<p>The two observations that helped here were:</p>

<ol>
<li>Once we reach all possible spots in a garden, following steps just cycle
between the same two sets of reachable spots. Meaning once we spend enough
time in a garden, we know how many steps are reachable in that particular
garden by just looking at the modulo of total number of steps.</li>
<li>As the number of steps increases over the infinitely repeating garden, there
is a pattern to how the covered area grows. This is a diamond shape where the
center is always fully covered garden tiles (see the first observation above)
and the surrounding tiles are at various stages of being visited.</li>
</ol>

<p>In fact, after we grow beyond the first 4 surrounding tiles, it seems like the
garden grows with a periodicity of the size of the garden. Meaning every
<code>len(grid)</code> steps, we reach new tiles. There are a few cases to consider -
north, east, south, west, diagonals.</p>

<p>My approach was to do a probe - simulate the first few steps and record the
results.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">probe</span><span class="p">():</span>
    <span class="n">dx</span><span class="p">,</span> <span class="n">dy</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">//</span> <span class="mi">2</span>
    <span class="n">tiles</span><span class="p">,</span> <span class="n">progress</span> <span class="o">=</span> <span class="p">{(</span><span class="n">dx</span><span class="p">,</span> <span class="n">dy</span><span class="p">)},</span> <span class="p">{(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="p">{</span><span class="mi">0</span><span class="p">:</span> <span class="mi">1</span><span class="p">}}</span>
    
    <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">progress</span><span class="p">)</span> <span class="o">&lt;</span> <span class="mi">41</span><span class="p">:</span>
        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">new_tiles</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
        <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">tiles</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">grid</span><span class="p">[(</span><span class="n">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)][</span><span class="n">y</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])]</span> <span class="o">!=</span> <span class="s1">'#'</span><span class="p">:</span>
                <span class="n">new_tiles</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
            <span class="k">if</span> <span class="n">grid</span><span class="p">[(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)][</span><span class="n">y</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])]</span> <span class="o">!=</span> <span class="s1">'#'</span><span class="p">:</span>
                <span class="n">new_tiles</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">))</span>
            <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)][(</span><span class="n">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])]</span> <span class="o">!=</span> <span class="s1">'#'</span><span class="p">:</span>
                <span class="n">new_tiles</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
            <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">x</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)][(</span><span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])]</span> <span class="o">!=</span> <span class="s1">'#'</span><span class="p">:</span>
                <span class="n">new_tiles</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>

        <span class="n">tiles</span> <span class="o">=</span> <span class="n">new_tiles</span>

        <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="n">tiles</span><span class="p">:</span>
            <span class="n">sq_x</span><span class="p">,</span> <span class="n">sq_y</span> <span class="o">=</span> <span class="n">x</span> <span class="o">//</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">),</span> <span class="n">y</span> <span class="o">//</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">sq_x</span><span class="p">,</span> <span class="n">sq_y</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">progress</span><span class="p">:</span>
                <span class="n">progress</span><span class="p">[(</span><span class="n">sq_x</span><span class="p">,</span> <span class="n">sq_y</span><span class="p">)]</span> <span class="o">=</span> <span class="p">{}</span>
            <span class="k">if</span> <span class="n">i</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">progress</span><span class="p">[(</span><span class="n">sq_x</span><span class="p">,</span> <span class="n">sq_y</span><span class="p">)]:</span>
                <span class="n">progress</span><span class="p">[(</span><span class="n">sq_x</span><span class="p">,</span> <span class="n">sq_y</span><span class="p">)][</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
            <span class="n">progress</span><span class="p">[(</span><span class="n">sq_x</span><span class="p">,</span> <span class="n">sq_y</span><span class="p">)][</span><span class="n">i</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="n">progress</span>
</pre></div>

<p>Here <code>progress</code> keeps track, for each tile (keyed as set of <code>(x, y)</code> coordinates
offset from <code>(0, 0)</code>), of how many spots are reachable at a given time. I run
this until <code>progress</code> grows enough for the repeating pattern to show - because
we start from the center of a garden but in all other tiles we enter from a
side, it takes a couple of iterations for the pattern to stabilize. My guess is
this probe could be smaller with some better math, but that's what I have.</p>

<p>With this, given a number of steps, we can reduce it using <code>steps % len(grid)</code>
to a smaller value we can loop in our <code>progress</code> record. The reasoning being, if
the pattern repeats, it doesn't really matter whether we are 3 steps into tile
<code>(-1000, 0)</code> or 3 steps into tile <code>(-3, 0)</code>.</p>

<p>The tedious part was determining the right offsets and special cases when
computing the total number of squares. For example, even for the tiles that are
fully covered, we'll have a subset where tiles are on the <q>odd</q> state of squares
and a subset where tiles are on the âeven" state.</p>

<p>I ended up with the following formula (which might still be buggy, but seemed to
have worked for my input):</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">at</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">step</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">progress</span><span class="p">[(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)][</span><span class="n">step</span><span class="p">]</span> <span class="k">if</span> <span class="n">step</span> <span class="ow">in</span> <span class="n">progress</span><span class="p">[(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]</span> <span class="k">else</span> <span class="mi">0</span>


<span class="k">def</span><span class="w"> </span><span class="nf">count</span><span class="p">(</span><span class="n">steps</span><span class="p">):</span>
    <span class="n">even</span><span class="p">,</span> <span class="n">odd</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">if</span> <span class="n">steps</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">else</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>

    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">steps</span> <span class="o">//</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)):</span>
        <span class="k">if</span> <span class="n">steps</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">even</span> <span class="o">+=</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">i</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">odd</span> <span class="o">+=</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">i</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">odd</span> <span class="o">+=</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">i</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">even</span> <span class="o">+=</span> <span class="mi">4</span> <span class="o">*</span> <span class="n">i</span>

    <span class="n">total</span> <span class="o">=</span> <span class="n">even</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="n">odd</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>

    <span class="n">total</span> <span class="o">+=</span> <span class="n">at</span><span class="p">(</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">at</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">at</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">at</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">3</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>

    <span class="n">i</span> <span class="o">=</span> <span class="n">steps</span> <span class="o">//</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>

    <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    
    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
    
    <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="o">-</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span> <span class="o">*</span> <span class="n">at</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> <span class="n">steps</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">))</span>
    
    <span class="k">return</span> <span class="n">total</span>
</pre></div>

<p>I'm covering all inner <q>even</q> and âodd" tiles, then the directly north, east,
south, and west tiles, then two layers of diagonals. Again, I have a feeling
this could be simpler, but I didn't bother to optimize it further.</p>

<h2>Day 22</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/22">here</a>.</p>

<h3>Part 1</h3>

<p>For part one, we sort bricks by <code>z</code> coordinate (ascending), then we make each
brick <q>fall</q>. We do this by decrementing their <code>z</code> coordinate and checking
whether they intersect with any other brick.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">intersect</span><span class="p">(</span><span class="n">brick1</span><span class="p">,</span> <span class="n">brick2</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">brick1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">x</span> <span class="o">&gt;</span> <span class="n">brick2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">x</span> <span class="ow">or</span> <span class="n">brick1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">x</span> <span class="o">&lt;</span> <span class="n">brick2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">x</span><span class="p">:</span>
        <span class="k">return</span> <span class="kc">False</span>
    
    <span class="k">if</span> <span class="n">brick1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">y</span> <span class="o">&gt;</span> <span class="n">brick2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">y</span> <span class="ow">or</span> <span class="n">brick1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">y</span> <span class="o">&lt;</span> <span class="n">brick2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">y</span><span class="p">:</span>
        <span class="k">return</span> <span class="kc">False</span>
    
    <span class="k">if</span> <span class="n">brick1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="o">&gt;</span> <span class="n">brick2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="ow">or</span> <span class="n">brick1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="o">&lt;</span> <span class="n">brick2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">z</span><span class="p">:</span>
        <span class="k">return</span> <span class="kc">False</span>
    
    <span class="k">return</span> <span class="kc">True</span>


<span class="k">def</span><span class="w"> </span><span class="nf">slide_down</span><span class="p">(</span><span class="n">brick</span><span class="p">,</span> <span class="n">delta</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">Point</span><span class="p">(</span><span class="n">brick</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">brick</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">y</span><span class="p">,</span> <span class="n">brick</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="o">-</span> <span class="n">delta</span><span class="p">),</span> <span class="n">Point</span><span class="p">(</span><span class="n">brick</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">brick</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">y</span><span class="p">,</span> <span class="n">brick</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="o">-</span> <span class="n">delta</span><span class="p">))</span>


<span class="k">def</span><span class="w"> </span><span class="nf">fall</span><span class="p">(</span><span class="n">brick</span><span class="p">):</span>
    <span class="k">if</span> <span class="nb">min</span><span class="p">(</span><span class="n">brick</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">z</span><span class="p">,</span> <span class="n">brick</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">z</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span> <span class="mi">0</span>

    <span class="n">result</span><span class="p">,</span> <span class="n">orig</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">brick</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">brick</span> <span class="o">=</span> <span class="n">slide_down</span><span class="p">(</span><span class="n">brick</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
        <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">bricks</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">b</span> <span class="o">==</span> <span class="n">orig</span><span class="p">:</span>
                <span class="k">continue</span>

            <span class="k">if</span> <span class="n">intersect</span><span class="p">(</span><span class="n">brick</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
                <span class="k">return</span> <span class="n">result</span>

        <span class="n">result</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="nb">min</span><span class="p">(</span><span class="n">brick</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">z</span><span class="p">,</span> <span class="n">brick</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">z</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">result</span>


<span class="n">bricks</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">bricks</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">b</span><span class="p">:</span> <span class="nb">min</span><span class="p">(</span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">z</span><span class="p">,</span> <span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">z</span><span class="p">))</span>

<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">brick</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">bricks</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">delta</span> <span class="o">:=</span> <span class="n">fall</span><span class="p">(</span><span class="n">brick</span><span class="p">):</span>
        <span class="n">bricks</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">slide_down</span><span class="p">(</span><span class="n">brick</span><span class="p">,</span> <span class="n">delta</span><span class="p">)</span>
</pre></div>

<p>Once every brick that could fall has fallen to its final position, we need to
find the <q>critical</q> bricks - the bricks that are the only support for some other
bricks. We do this by shifting down each brick again 1 <code>z</code> and determining how
many bricks it intersects with. If a shifted brick only intersects with one
other brick, that is a âcritical<q>brick, so we add it to our set of âcritical</q>
support bricks. All other bricks can be safely removed.</p>
<div class="highlight"><pre><span/><span class="n">critical</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">for</span> <span class="n">brick</span> <span class="ow">in</span> <span class="n">bricks</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">brick</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">brick</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">continue</span>

    <span class="n">supported_by</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">nb</span> <span class="o">=</span> <span class="n">slide_down</span><span class="p">(</span><span class="n">brick</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">bricks</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">brick</span> <span class="o">==</span> <span class="n">b</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="k">if</span> <span class="n">intersect</span><span class="p">(</span><span class="n">nb</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
            <span class="n">supported_by</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>

    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">supported_by</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">critical</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">supported_by</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>

<span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">bricks</span><span class="p">)</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">critical</span><span class="p">))</span>
</pre></div>

<h3>Part 2</h3>

<p>In part 2, we need to figure out which bricks is each brick supported by. We can
use a similar algorithm to part 1, where we shift <code>z</code> by 1 and check which
bricks we intersect. Then we can build a dependency graph of which bricks is
supported by which other bricks.</p>
<div class="highlight"><pre><span/><span class="n">supported_by</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">brick</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">bricks</span><span class="p">):</span>
    <span class="n">supported_by</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>

    <span class="k">if</span> <span class="n">brick</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">brick</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">z</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">continue</span>

    <span class="n">nb</span> <span class="o">=</span> <span class="n">slide_down</span><span class="p">(</span><span class="n">brick</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">for</span> <span class="n">j</span><span class="p">,</span> <span class="n">b</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">bricks</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="n">j</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="k">if</span> <span class="n">intersect</span><span class="p">(</span><span class="n">nb</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
            <span class="n">supported_by</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>
</pre></div>

<p>Then for each brick we remove, we can walk the <q>supported by</q> dependencies to
determine which bricks would fall and would, in turn, cause other bricks to
fall, without having to actually simulate falling.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">count_falling</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
    <span class="n">sup</span> <span class="o">=</span> <span class="p">{</span><span class="n">k</span><span class="p">:</span> <span class="n">supported_by</span><span class="p">[</span><span class="n">k</span><span class="p">]</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span> <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">supported_by</span><span class="o">.</span><span class="n">keys</span><span class="p">()}</span>
    <span class="n">queue</span><span class="p">,</span> <span class="n">removed</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="nb">set</span><span class="p">()</span>
    <span class="k">while</span> <span class="n">queue</span><span class="p">:</span>
        <span class="n">i</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        
        <span class="k">if</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">removed</span><span class="p">:</span>
            <span class="k">continue</span>
        <span class="n">removed</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>

        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">sup</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">sup</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
                <span class="n">sup</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
                <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sup</span><span class="p">[</span><span class="n">j</span><span class="p">])</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">j</span><span class="p">)</span>

    <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="n">removed</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>


<span class="nb">print</span><span class="p">(</span><span class="nb">sum</span><span class="p">(</span><span class="n">count_falling</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">supported_by</span><span class="p">))))</span>
</pre></div>

<h2>Day 23</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/23">here</a>.</p>

<p>The main insight here for both part 1 and part 2 is that we can model the paths
as a graph where each intersection (decision point) is a vertex and the paths
between intersections are edges. With this representation, we simply need to
find the longest path between our starting point and our end point.</p>

<p>In part 1, we have a directed graph, as right before hitting each intersection,
we have a <code>&gt;&lt;^v</code> constraint, making the path one-way. In part 2, we have an
undirected graph.</p>

<p>Note that the longest path problem in a graph is harder than the shortest path
problem. That said, we are dealing with extremely small graphs.</p>

<h2>Day 24</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/24">here</a>.</p>

<h3>Part 1</h3>

<p>Part 1 was fairly straightforward: for each pair of lines, solve the equation to
find where they meet and check if within bounds (when lines are not parallel).</p>

<p>Since each line is described by a point \((x_{origin}, y_{origin})\) and a vector \((dx, dy)\), we
can represent them as</p>

<p>\[\begin{cases}
x = x_{origin} + dx * t \\
y = y_{origin} + dy * t
\end{cases}\]</p>

<p>Then the lines intersect when</p>

<p>\[\begin{cases}
x_1 + dx_1 * t_1 = x_2 + dx_2 * t_2 \\
y_1 + dy_1 * t_1 = y_2 + dy_2 * t_2
\end{cases}\]</p>

<p>We know all of \((x_1, y_1), (dx_1, dy_1), (x_2, y_2), (dx_2, dy_2)\) so we solve
for \(t_1\) and \(t_2\).</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">intersect</span><span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="n">v1</span><span class="p">,</span> <span class="n">p2</span><span class="p">,</span> <span class="n">v2</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">v1</span><span class="o">.</span><span class="n">dx</span> <span class="o">/</span> <span class="n">v1</span><span class="o">.</span><span class="n">dy</span> <span class="o">==</span> <span class="n">v2</span><span class="o">.</span><span class="n">dx</span> <span class="o">/</span> <span class="n">v2</span><span class="o">.</span><span class="n">dy</span><span class="p">:</span>
        <span class="k">return</span> <span class="kc">None</span><span class="p">,</span> <span class="kc">None</span>

    <span class="n">t2</span> <span class="o">=</span> <span class="p">(</span><span class="n">v1</span><span class="o">.</span><span class="n">dx</span> <span class="o">*</span> <span class="p">(</span><span class="n">p2</span><span class="o">.</span><span class="n">y</span> <span class="o">-</span> <span class="n">p1</span><span class="o">.</span><span class="n">y</span><span class="p">)</span> <span class="o">+</span> <span class="n">v1</span><span class="o">.</span><span class="n">dy</span> <span class="o">*</span> <span class="p">(</span><span class="n">p1</span><span class="o">.</span><span class="n">x</span> <span class="o">-</span> <span class="n">p2</span><span class="o">.</span><span class="n">x</span><span class="p">))</span> <span class="o">/</span> <span class="p">(</span><span class="n">v2</span><span class="o">.</span><span class="n">dx</span> <span class="o">*</span> <span class="n">v1</span><span class="o">.</span><span class="n">dy</span> <span class="o">-</span> <span class="n">v2</span><span class="o">.</span><span class="n">dy</span> <span class="o">*</span> <span class="n">v1</span><span class="o">.</span><span class="n">dx</span><span class="p">)</span>
    <span class="n">t1</span> <span class="o">=</span> <span class="p">(</span><span class="n">p2</span><span class="o">.</span><span class="n">y</span> <span class="o">+</span> <span class="n">v2</span><span class="o">.</span><span class="n">dy</span> <span class="o">*</span> <span class="n">t2</span> <span class="o">-</span> <span class="n">p1</span><span class="o">.</span><span class="n">y</span><span class="p">)</span> <span class="o">/</span> <span class="n">v1</span><span class="o">.</span><span class="n">dy</span>

    <span class="k">return</span> <span class="n">t1</span><span class="p">,</span> <span class="n">t2</span>
</pre></div>

<p>Once we have <code>t1</code> and <code>t2</code>, we need to check both are positive (so intersection didn't happen in the past), and make sure the intersection point, which is either <code>x1 + dx1 * t1</code>, <code>y1 + dx1 * t1</code> or <code>x2 + dx2 * t2</code>, <code>y2 + dx2 * t2</code>, is within our bounds (at leastÂ 200000000000000Â and at mostÂ 400000000000000).</p>

<p>If that's the case, then we found an intersection and we can add it to the total.</p>

<h3>Part 2</h3>

<p>Part 2 was really fun. We now have 3 dimensions, so a line is represented as</p>

<p>\[\begin{cases}
x = x_{origin} + dx * t \\
y = y_{origin} + dy * t \\
z = z_{origin} + dz * t
\end{cases}\]</p>

<p>We need to find a line (the trajectory of our rock) that intersects each line in
our input at a different time, such that for some \(t\) and line \(l\), we have</p>

<p>\[\begin{cases}
x_{origin_{l}} + dx_l * t = x_{origin_{rock}} + dx_{rock} * t \\
y_{origin_{l}} + dy_l * t = y_{origin_{rock}} + dy_{rock} * t \\
z_{origin_{l}} + dz_l * t = z_{origin_{rock}} + dz_{rock} * t
\end{cases}\]</p>

<p>One way to solve this is using linear algebra. If we take 3 different hailstorms
and our rock, we end up with the following set of equations:</p>

<p>\[\begin{cases}
x_{origin_{1}} + dx_1 * t_1 = x_{origin_{rock}} + dx_{rock} * t_1 \\
y_{origin_{1}} + dy_1 * t_1 = y_{origin_{rock}} + dy_{rock} * t_1 \\
z_{origin_{1}} + dz_1 * t_1 = z_{origin_{rock}} + dz_{rock} * t_1 \\
x_{origin_{2}} + dx_2 * t_2 = x_{origin_{rock}} + dx_{rock} * t_2 \\
y_{origin_{2}} + dy_2 * t_2 = y_{origin_{rock}} + dy_{rock} * t_2 \\
z_{origin_{2}} + dz_2 * t_2 = z_{origin_{rock}} + dz_{rock} * t_2 \\
x_{origin_{3}} + dx_3 * t_3 = x_{origin_{rock}} + dx_{rock} * t_3 \\
y_{origin_{3}} + dy_3 * t_3 = y_{origin_{rock}} + dy_{rock} * t_3 \\
z_{origin_{3}} + dz_3 * t_3 = z_{origin_{rock}} + dz_{rock} * t_3
\end{cases}\]</p>

<p>In the above system, we know all of the starting points and vectors of the
hailstorms. Our unknowns are \(t_1\), \(t_2\), \(t_3\), \(x_{origin_{rock}}\),
\(y_{origin_{rock}}\), \(z_{origin_{rock}}\), \(dx_{rock}\), \(dy_{rock}\), \(dz_{rock}\).
That's 9 unknowns to 9 equations, so it should be solvable.</p>

<p>While this approach works, I didn't want to use a numerical library to solve
this (I'm trying to keep dependencies at a minimum), and implementing the math
from scratch was a bit too much for me. I thought of a different approach: as
long as we can find a rock trajectory that intersects the first couple of
hailstorms at the right times, we most likely found our solution.</p>

<p>\[\begin{cases}
x_{origin_{rock}} + dx_{rock} * t_1 = x_1 + dx_1 * t_1 \\
y_{origin_{rock}} + dy_{rock} * t_1 = y_1 + dy_1 * t_1 \\
x_{origin_{rock}} + dx_{rock} * t_2 = x_2 + dx_2 * t_2 \\
y_{origin_{rock}} + dy_{rock} * t_2 = y_2 + dy_2 * t_2
\end{cases}\]</p>

<p>If we solve this for \(t_1\) and \(t_2\), we can then easily determine
\(z_{origin_{rock}}\) and \(dz_{rock}\).</p>

<p>In the above set of equations, we have too many unknowns: \(x_{origin_{rock}},
dx_{rock}, y_{origin_{rock}}, dy_{rock}, t_1, t_2\). We can reduce this number
by trying out different values for a couple of these unknowns. While the ranges
of possible values for \(x_{origin_{rock}}, y_{origin_{rock}}, t_1, t_2\) are
very large, so unfeasible to cover, \(dx_{origin}\) and \(dy_{origin}\) ranges
should be small - if these values are large, our rock will quickly shoot past
all the other hailstorms.</p>

<p>My approach was to try all possible values between -1000 and 1000 for both of
these, then see if we can find \(x_{origin_{rock}}, y_{origin_{rock}}, t_1,
t_2\) such that these intersect the first two hailstorms. If we do, we then
find \(z_{origin_{rock}}, dz_{rock}\) (easy to find since now we know \(t_1, t_2\)).
We have an additional helpful constraint: the origin coordinates of the rock
need to be integers.</p>

<p>Then we just need to check that indeed for the given \((x_{origin_{rock}},
y_{origin_{rock}}, z_{origin_{rock}})\) and \((dx_{rock}, dy_{rock}, dz_{rock})\),
for each hailstorm, there is a time \(t_i\) when they intersect.</p>

<p>Here is the code:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">find</span><span class="p">(</span><span class="n">rng</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">dx</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="n">rng</span><span class="p">,</span> <span class="n">rng</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">dy</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="o">-</span><span class="n">rng</span><span class="p">,</span> <span class="n">rng</span><span class="p">):</span>
            <span class="n">x1</span><span class="p">,</span> <span class="n">y1</span><span class="p">,</span> <span class="n">z1</span> <span class="o">=</span> <span class="n">hails</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
            <span class="n">dx1</span><span class="p">,</span> <span class="n">dy1</span><span class="p">,</span> <span class="n">dz1</span> <span class="o">=</span> <span class="n">hails</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
            <span class="n">x2</span><span class="p">,</span> <span class="n">y2</span><span class="p">,</span> <span class="n">z2</span> <span class="o">=</span> <span class="n">hails</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
            <span class="n">dx2</span><span class="p">,</span> <span class="n">dy2</span><span class="p">,</span> <span class="n">dz2</span> <span class="o">=</span> <span class="n">hails</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>

            <span class="c1"># x + dx * t1 = x1 + dx1 * t1</span>
            <span class="c1"># y + dy * t1 = y1 + dy1 * t1</span>
            <span class="c1"># x + dx * t2 = x2 + dx2 * t2</span>
            <span class="c1"># y + dy * t2 = y2 + dy2 * t2</span>

            <span class="c1"># x = x1 + t1 * (dx1 - dx)        </span>
            <span class="c1"># t1 = (x2 - x1 + t2 * (dx2 - dx)) / (dx1 - dx)</span>
            <span class="c1"># y = y1 + (x2 - x1 + t2 * (dx2 - dx)) * (dy1 - dy) / (dx1 - dx)</span>
            <span class="c1"># t2 = ((y2 - y1) * (dx1 - dx) - (dy1 - dy) * (x2 - x1)) / ((dy1 - dy) * (dx2 - dx) + (dy - dy2) * (dx1 - dx))</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">dy1</span> <span class="o">-</span> <span class="n">dy</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">dx2</span> <span class="o">-</span> <span class="n">dx</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">dy</span> <span class="o">-</span> <span class="n">dy2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">dx1</span> <span class="o">-</span> <span class="n">dx</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="k">continue</span>

            <span class="n">t2</span> <span class="o">=</span> <span class="p">((</span><span class="n">y2</span> <span class="o">-</span> <span class="n">y1</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">dx1</span> <span class="o">-</span> <span class="n">dx</span><span class="p">)</span> <span class="o">-</span> <span class="p">(</span><span class="n">dy1</span> <span class="o">-</span> <span class="n">dy</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">x2</span> <span class="o">-</span> <span class="n">x1</span><span class="p">))</span> <span class="o">/</span> <span class="p">((</span><span class="n">dy1</span> <span class="o">-</span> <span class="n">dy</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">dx2</span> <span class="o">-</span> <span class="n">dx</span><span class="p">)</span> <span class="o">+</span> <span class="p">(</span><span class="n">dy</span> <span class="o">-</span> <span class="n">dy2</span><span class="p">)</span> <span class="o">*</span> <span class="p">(</span><span class="n">dx1</span> <span class="o">-</span> <span class="n">dx</span><span class="p">))</span>

            <span class="k">if</span> <span class="ow">not</span> <span class="n">t2</span><span class="o">.</span><span class="n">is_integer</span><span class="p">()</span> <span class="ow">or</span> <span class="n">t2</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
                <span class="k">continue</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">dx1</span> <span class="o">-</span> <span class="n">dx</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="k">continue</span>

            <span class="n">y</span> <span class="o">=</span> <span class="n">y1</span> <span class="o">+</span> <span class="p">(</span><span class="n">x2</span> <span class="o">-</span> <span class="n">x1</span> <span class="o">+</span> <span class="n">t2</span> <span class="o">*</span> <span class="p">(</span><span class="n">dx2</span> <span class="o">-</span> <span class="n">dx</span><span class="p">))</span> <span class="o">*</span> <span class="p">(</span><span class="n">dy1</span> <span class="o">-</span> <span class="n">dy</span><span class="p">)</span> <span class="o">/</span> <span class="p">(</span><span class="n">dx1</span> <span class="o">-</span> <span class="n">dx</span><span class="p">)</span>

            <span class="k">if</span> <span class="ow">not</span> <span class="n">y</span><span class="o">.</span><span class="n">is_integer</span><span class="p">():</span>
                <span class="k">continue</span>

            <span class="n">t1</span> <span class="o">=</span> <span class="p">(</span><span class="n">x2</span> <span class="o">-</span> <span class="n">x1</span> <span class="o">+</span> <span class="n">t2</span> <span class="o">*</span> <span class="p">(</span><span class="n">dx2</span> <span class="o">-</span> <span class="n">dx</span><span class="p">))</span> <span class="o">/</span> <span class="p">(</span><span class="n">dx1</span> <span class="o">-</span> <span class="n">dx</span><span class="p">)</span>

            <span class="k">if</span> <span class="ow">not</span> <span class="n">t1</span><span class="o">.</span><span class="n">is_integer</span><span class="p">()</span> <span class="ow">or</span> <span class="n">t1</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
                <span class="k">continue</span>

            <span class="n">x</span> <span class="o">=</span> <span class="n">x1</span> <span class="o">+</span> <span class="n">t1</span> <span class="o">*</span> <span class="p">(</span><span class="n">dx1</span> <span class="o">-</span> <span class="n">dx</span><span class="p">)</span>        

            <span class="c1"># z + dz * t1 = z1 + dz1 * t1</span>
            <span class="c1"># z + dz * t2 = z2 + dz2 * t2        </span>

            <span class="c1"># dz = (z1 + dz1 * t1 - z2 - dz2 * t2) / (t1 - t2)</span>
            <span class="c1"># z = z1 + dz1 * t1 - dz * t1</span>

            <span class="k">if</span> <span class="n">t1</span> <span class="o">==</span> <span class="n">t2</span><span class="p">:</span>
                <span class="k">continue</span>

            <span class="n">dz</span> <span class="o">=</span> <span class="p">(</span><span class="n">z1</span> <span class="o">+</span> <span class="n">dz1</span> <span class="o">*</span> <span class="n">t1</span> <span class="o">-</span> <span class="n">z2</span> <span class="o">-</span> <span class="n">dz2</span> <span class="o">*</span> <span class="n">t2</span><span class="p">)</span> <span class="o">/</span> <span class="p">(</span><span class="n">t1</span> <span class="o">-</span> <span class="n">t2</span><span class="p">)</span>

            <span class="k">if</span> <span class="ow">not</span> <span class="n">dz</span><span class="o">.</span><span class="n">is_integer</span><span class="p">():</span>
                <span class="k">continue</span>

            <span class="n">z</span> <span class="o">=</span> <span class="n">z1</span> <span class="o">+</span> <span class="n">dz1</span> <span class="o">*</span> <span class="n">t1</span> <span class="o">-</span> <span class="n">dz</span> <span class="o">*</span> <span class="n">t1</span>
</pre></div>

<p>In the above <code>x</code>, <code>y</code>, <code>z</code>, <code>dx</code>, <code>dy</code>, <code>dz</code> are the rock's origin and vector.</p>

<p>The final step (omitted from the code sample for brevity), is to confirm that
for the given origin and vector, we end up eventually intersecting all other
hailstorms.</p>

<p>I really enjoyed this problem as it made me work through the math.</p>

<h2>Day 25</h2>

<p>Problem statement is <a href="https://adventofcode.com/2023/day/25">here</a>.</p>

<p>I liked this problem. It turned out to be a variation of the <a href="https://en.wikipedia.org/wiki/Minimum_cut">minimum cut
problem</a>. Trying out all possible
permutations of nodes would take way too much time. The algorithm I used keeps
track of a set of <em>visited</em> nodes - one of the two components. Then at each
step, we add a new node to this set by selecting the most connected node to this
component (meaning the node that has most edges incoming from visited nodes).</p>

<p><code>most_connected()</code> determines which node we want to pick next:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">most_connected</span><span class="p">(</span><span class="n">visited</span><span class="p">):</span>
    <span class="n">best_n</span><span class="p">,</span> <span class="n">best_d</span> <span class="o">=</span> <span class="kc">None</span><span class="p">,</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="n">neighbors</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">(</span><span class="mi">1</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="k">if</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">neighbors</span> <span class="o">&gt;</span> <span class="n">best_d</span><span class="p">:</span>
            <span class="n">best_n</span><span class="p">,</span> <span class="n">best_d</span> <span class="o">=</span> <span class="n">n</span><span class="p">,</span> <span class="n">neighbors</span>

    <span class="k">return</span> <span class="n">best_n</span>
</pre></div>

<p>Then we keep going until our component has exactly 3 outgoing edges to nodes
that haven't ben visited yet:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">find_components</span><span class="p">():</span>
    <span class="n">start</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">graph</span><span class="o">.</span><span class="n">keys</span><span class="p">())[</span><span class="mi">0</span><span class="p">]</span>
    <span class="n">visited</span> <span class="o">=</span> <span class="p">{</span><span class="n">start</span><span class="p">}</span>
    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">visited</span><span class="p">)</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">graph</span><span class="p">):</span>
        <span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
            <span class="n">total</span> <span class="o">+=</span> <span class="nb">sum</span><span class="p">(</span><span class="mi">1</span> <span class="k">for</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">graph</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="k">if</span> <span class="n">v</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">)</span>
        
        <span class="k">if</span> <span class="n">total</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">visited</span>

        <span class="n">n</span> <span class="o">=</span> <span class="n">most_connected</span><span class="p">(</span><span class="n">visited</span><span class="p">)</span>
        <span class="n">visited</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</pre></div>

<p>That's where we need to make the cut. We just need to multiply <code>len(visited)</code>
with <code>len(graph) - len(visited)</code> to find our answer.</p>

<p>I personally found the most difficult problems to be part 2 of day 20, 21, 24
and the one and only part of day 25. All of these took me a bit to figure out.
That said, Advent of Code is always a nice holiday past-time and I can't wait
for the 2024 iteration.</p>
]]></description>
      <pubDate>Wed, 10 Jan 2024 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/12/28/notes-on-platform-development.html</link>
      <guid>https://vladris.com/blog/2023/12/28/notes-on-platform-development.html</guid>
      <title><![CDATA[Notes on Platform Development]]></title>
      <description><![CDATA[<h1>Notes on Platform Development</h1>

<p>I spent the past few years building a platform for Loop components within the
Microsoft 365 ecosystem. While some of the learnings might only apply to our
particular scenario, I think some observations apply broadly.</p>

<p>Weâve been using 1P/2P/3P to mean our team (1P), other teams within Microsoft
(2P), and external developers (3P). Loop started with a set of 1P components and
we set out to extract a developer platform out of these that can be leveraged by
other teams. We currently have a set of 2P components built on our platform, and
a 3P developer story centered around <a href="https://learn.microsoft.com/en-us/microsoftteams/platform/m365-apps/cards-loop-component">Adaptive Cards</a>.</p>

<p>In this blog post Iâll cover some of my learnings with regard to platform
development.</p>

<h2>1P != 3P</h2>

<p>Aspirationally, we set out with the stated goal of <em>1P equals 3P</em>, meaning 3rd
party developers should be building on the same platform as 1st party
developers. Looking at it another way, if the platform is good enough for 1st
party, it should be just as good for 3rd party - this is a statement of platform
capabilities and maturity and a lofty goal.</p>

<p>That said, I donât think this is realistic, especially within a product like
Office, where user experience is paramount. That is because we have two
audiences to consider: we have the developer audience - users building on our
platform, and we have Office users, people who get to use the end product.
Mediating between the two is quite a challenge.</p>

<p>A simple example is the classic performance/security tradeoff. Especially as
Loop components are embedded in other applications, what level of isolation do
we provide? Loop components are built with web technology. An iframe provides
great isolation (best security) but iframes add performance overhead (worse
perf). If we host a Loop component without an iframe, we get better performance,
but we open up the whole DOM to the component. If we threat model this, we
immediately see that we donât necessarily need isolation for Loop components
developed within Microsoft (we donât expect our partner teams to write malicious
code) but we absolutely need to isolate code written by 3rd party developers. Of
course, we could say âjust isolate everythingâ, which might even have other
advantages, but do we want to take the perf hit? Our <em>other</em> audience, people
who use our product, would be negatively impacted by an overhead we can
technically avoid.</p>

<p>Another example in the same vein: overall user experience. The more we make Loop
components feel like part of the hosting app, the smoother the end user
experience is. On the other hand, we canât realistically test every single Loop
component built by any 3rd party developer. The way Office services and products
are deployed and administered, tenant admins can configure which 3rd party
extensions are enabled within the tenant. The Microsoft tenant we use internally
has set some set of extensions available, but not all. That means there are
always 3rd party extensions we never even see. Now if one of these extensions
doesnât work properly (errors out, looks out of place, is slow etc.), end users
might end up dissatisfied with the overall experience of using Office products.
For internally developed components, we get to dogfood and keep a high bar, but
this doesnât scale to a wide developer audience. Our current approach is to
offer 3rd party development via Adaptive Cards. This way, we donât run 3rd party
code on clients and we have a set of consistent UI controls. Ideally, weâd like
to enable custom code but this at the time of writing weâre still thinking
through the best approach considering all of the challenges listed above.</p>

<p>Finally, I think another key difference is the product goals. The platform
audience are the developers, but the product audience are the users. Thereâs
usually a tension between these. For example, an internal team builds a Loop
component. They come up with a requirement that is a âmustâ to deliver their
scenario. For example, we had a component developed by a partner team that asked
us to check the tenantâs Cloud Policy service to see whether the component
should be <em>on</em> or <em>off</em>. This makes perfect sense in this case, since the
backing service might not be running in the tenant. We offer tenant admins a
different way to control 3rd party extensions, so this platform capability would
not make sense for a 3rd party. In general, a lot of our internal platform
capability requests come from the desire to provide the best possible end user
experience. If our only customer were the developers using the platform, we
would probably say ânoâ to some of these - not general enough, doesnât benefit
3rd party etc. But, of course, Office has way more users than developers.</p>

<p>I think the 1P/3P challenge is common to most platforms built from within
product teams (or supporting product teams within the same company). With Loop,
this is compounded by the fact we are deeply integrated within other
applications. I can think of some notable examples when the strong push for a
â1P equals 3Pâ platform ended up disastrously - Windows Longhorn was supposed to
be built on a version of .NET that was just not good enough for core OS pieces.
I can also think of many platforms that provide sufficient capabilities for 3rd
party developers but 1st/2nd party developers donât use. And I think this is
OK - building a platform for 3P lets you focus on the developer community needs.
Supporting 1P/2P might be best served by focusing on the product goals and
unique scenario needs rather than trying to generalize to a public platform.</p>

<h2>Life stages</h2>

<p>A platform goes through several life stages, each with its own characteristics
and challenges. Looking back at how our platform evolved (and how I foresee the
future), a successful platform goes through 4 life stages: <em>incubation</em>, <em>0 to
1</em>, <em>stabilization</em>, and <em>commoditization</em>.</p>

<h3>Incubation</h3>

<p>At this stage, itâs all one team building both the what-will-become-a-platform
and the product supported by this platform. During the incubation stage, the
platform doesnât really have any  users (meaning developers leveraging the
platform). We are free to toy with ideas. If we want to make a breaking change
to an API, we can easily do it and fix the handful of internal calls. At this
point, everything is in flux - the canvas is blank and we have plenty of room to
innovate.</p>

<p>On the other hand, we donât really have a clear idea of what developers would
need out of the platform - we know what the main scenario we are supporting
needs, but we donât have a feedback loop yet. At this stage, we need to rely on
experience and intuition to set some initial direction.</p>

<h3>0 to 1</h3>

<p>This is the biggest growth stage. â0 to 1â is a nod to Peter Thielâs <a href="https://www.goodreads.com/book/show/18050143-zero-to-one">Zero to One</a> book. The
platform goes from no users to a few users - and by âusersâ here I mean
developers. Taking the platform from 0 (or incubation) to 1, means supporting a
handful of âseriousâ production scenarios.</p>

<p>We now have a feedback loop and developers able to give us requirements - we can
now understand their needs rather than have to divine them ourselves. As a side
note, this is the approach we took with Loop, where we worked closely with a set
of 2P partners to light up scenarios and grow the platform to support these.</p>

<p>At this stage, itâs already difficult to make breaking changes. Since there are
already a set of dependencies on the platform, a breaking change requires a lot
of coordination. Or some form of backwards compatibility. Or legacy support.
There are different ways to go about this (maybe in another blog post), but the
key point is we can no longer churn as fast as we could during the incubation
stage. And added costs at the 0 to 1 stage are painful.</p>

<p>Another challenge is generalization. We have a handful of partners with a
handful of requests for the platform. And weâre in the growth stage, so we most
likely need to move fast. Thereâs a big tension between how fast we can light up
new platform capabilities and how much time we spend thinking through design
patterns and future-proofing. If we just say âyesâ to every ask, we can move
fast but risk ending up with a very gnarly platform that has many one-off pieces
and a very inconsistent developer story. On the other hand, we can spend a lot
of time iterating on design and predicting how an incoming requirement would
scale when the platform is large, all the way until our partners give up on us
or funding runs out. There is no silver bullet for this - you always end up
somewhere in the middle, with parts of the platform that you wished were done
differently, but hopefully still alive and kicking in the next stage.</p>

<h3>Stabilization</h3>

<p>At this point, enough developers depend on the platform that ad-hoc breaking
changes are no longer possible. By âstabilizationâ I donât mean the platform
stops growing - in fact, this is the stage where we get most feedback and
requests. But while the platform continues to grow incrementally, changes become
even more difficult as they can break the whole ecosystem.</p>

<p>There are now enough user that early design decision that proved wrong become
obvious, but itâs too late to change them. This is a natural âif I knew then
what I know nowâ point for any platform that canât really be avoided.</p>

<p>This is the point where most platform start producing new major version numbers
that aim to address large swats of issues and add new bundles of functionality.
But while during the incubation stage, a change could land in a few days, and in
the 0 to 1 stage maybe weeks or at most months, breaking changes at this stage
take years to land - many developers means not all of them are ready right-away
to update their code to the newest patterns. The platform needs some form of
long-term support for older versions and deprecation/removal becomes a long
journey.</p>

<p>On the other hand, the core of the platform is stable by now and battle-tested.
The final step is the platform becoming a commodity.</p>

<h3>Commoditization</h3>

<p>At this stage, the platform is mature and robust. A large developer community
depends on it and the platform is mostly feature complete. Some new requirements
might pop up from time to time, but not very often.</p>

<p>At this stage developers rely on existing behaviors and change is next to
impossible. Thatâs because a lot of the developer solutions are also âdoneâ by
now and people moved on. Nobody wants to go back and update things to support
API changes. The platform is a useful commodity.</p>

<p>This is also the stage where active development slows down and fewer engineers
are required to keep things going. We havenât reached this stage with Loop, we
are still growing the platform and moving fast. But any successfully platform
should reach this stage - a low-churn state where its capabilities (and gotchas)
are well understood and reliable.</p>

<p>Each of the stages require a different approach to evolving the platform. The
speed with which we add capabilities, churn, how updates are rolled out, how we
design new features - all happen in different ways and at a different pace
depending on where the platform is and its number of users.</p>

<h2>Summary</h2>

<p>In this post I covered two main aspects of platform development: the tension
between supporting 3rd party developers and ensuring end users have the best
possible experience; and the different stages of a platform. As usage increases,
changes become more difficult and early decisions solidify, for better or worse.</p>

<p>If I look at other platforms, I can easily see how they went through the same
growing pains and challenges.</p>

<p>Iâll probably have more to write on the topic of platform development, since
this has been my main job for a while now.</p>
]]></description>
      <pubDate>Thu, 28 Dec 2023 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/11/28/mental-poker-part-3-transport.html</link>
      <guid>https://vladris.com/blog/2023/11/28/mental-poker-part-3-transport.html</guid>
      <title><![CDATA[Mental Poker Part 3: Transport]]></title>
      <description><![CDATA[<h1>Mental Poker Part 3: Transport</h1>

<p>Now that my <a href="https://vladris.com/blog/2023/11/03/large-language-models-at-work-rtm.html">LLM book is done</a>,
I can get back to the Mental Poker series. A high-level overview can be found
<a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">here</a>.
In the previous posts we covered
<a href="https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html">cryptography</a>
and <a href="https://vladris.com/blog/2023/06/04/mental-poker-part-2-fluid-ledger.html">a Fluid append-only list data
structure</a>.
Weâll be using the append-only list (we called this <code>fluid-ledger</code>) to model
games.</p>

<p>An append-only list should be all that is needed to model turn-based games: each
<em>turn</em> is an element added to the list. In this post, weâll stitch things
together and look at the transport layer for our games.</p>

<h2>Transport</h2>

<p>Our basic transport interface is very simple:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">interface</span><span class="w"> </span><span class="nx">ITransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">getActions</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="nx">postAction</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="nx">once</span><span class="p">(</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="w">    </span><span class="nx">on</span><span class="p">(</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="w">    </span><span class="nx">off</span><span class="p">(</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>For some type <code>T</code>, we have:</p>

<ul>
<li>A <code>getActions()</code>, which returns an iterator over all values (of type <code>T</code>)
posted so far.</li>
<li>A <code>postAction()</code>, which takes a value of type <code>T</code> and an <code>actionPosted</code> event
which fires whenever any of the clients posts an action (this relies on the
Fluid data synchronization).</li>
<li>And the standard <code>EventEmitter</code> methods.</li>
</ul>

<p>We'll cover why we call these values <em>actions</em> in a future post.</p>

<p>The basic implementation of this on top of the <code>fluid-ledger</code> distributed data
structure looks like this:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">FluidTransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">EventEmitter</span><span class="w"> </span><span class="k">implements</span><span class="w"> </span><span class="nx">ITransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">ledger</span><span class="o">:</span><span class="w"> </span><span class="kt">ILedger</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">super</span><span class="p">();</span>
<span class="w">        </span><span class="nx">ledger</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s2">"append"</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">T</span><span class="p">);</span>
<span class="w">        </span><span class="p">});</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="o">*</span><span class="nx">getActions</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">ledger</span><span class="p">.</span><span class="nx">get</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">yield</span><span class="w"> </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">T</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">postAction</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nb">Promise</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">ledger</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="nb">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">value</span><span class="p">)));</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>The constructor takes an <code>ILedger&lt;string&gt;</code> (this is the interface we looked at
in <a href="https://vladris.com/blog/2023/06/04/mental-poker-part-2-fluid-ledger.html">the previous post</a>).</p>

<p>It hooks up an event listener to the ledger's <code>append</code> event to in turn trigger
an <code>actionPosted</code> event. We also convert the incoming value from <code>string</code> to <code>T</code>
using <code>JSON.parse()</code>.</p>

<p>Similarly, <code>getActions()</code> is a simple wrapper over the underlying ledger, doing
the same conversion to <code>T</code>.</p>

<p>Finally, the <code>postAction()</code> does the reverse - it converts from <code>T</code> to a string
and appends the value to the ledger.</p>

<p>With this in place, we abstracted away the Fluid-based transport details. We
will separately set up a Fluid container and establish connection to other
clients (in a future post), then take the <code>ILedger</code> instance, pass it to
<code>FluidTransport</code>, and we are good to go.</p>

<p>We can model games on top of just these two primitives: <code>postAction()</code> and
<code>actionPosted</code>. Whenever we take a turn, we call <code>postAction()</code>. Whenever any
player takes a turn, the <code>actionPosted</code> event is fired.</p>

<p>Since weâre designing Mental Poker, which takes place in a zero-trust
environment, letâs make sure our transport is secure.</p>

<h2>Signature verification</h2>

<p>Signature verification allows us to ensure that in a multiplayer game, players
canât spoof each other, meaning Alice canât pretend she is Bob and post an
action on Bobâs behalf for other clients to misinterpret.</p>

<p>Note in a 2-player game this is not strictly needed if we trust the channel: we
know that if a payload was not sent by us, it was sent by the other player. But
in games with more players, we need to protect against spoofing. Signatures are
also useful in case we donât trust the channel - maybe itâs supposed to be a
2-player game but a third client gets access to the channel and starts sending
messages.</p>

<p>We will implement this using public key cryptography. The way this works is each
player generates (locally) a public/private key pair. They broadcast the public
key to all other players. Then they can sign any message they send with their
private key and other players can validate the signature using the public key.
Nobody else can sign on their behalf, since the private key is kept private.</p>

<p>I wonât go into deeper detail here, since this is very standard public key
cryptography. In fact, I didnât even cover this in the blog post covering
<a href="https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html">cryptography</a>
for Mental Poker for this reason. There, I focused on the commutative SRA
encryption algorithm. Unlike SRA, which we had to implement by hand, signature
verification is part of the standard <a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Crypto_API">Web Crypto
API</a>. Letâs
implement signature verification on top of this.</p>

<p>First, we need to model a public/private key pair:</p>
<div class="highlight"><pre><span/><span class="c1">// Keys are represented as strings</span>
<span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">Key</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>

<span class="c1">// Public/private key pair</span>
<span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">PublicPrivateKeyPair</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">publicKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span><span class="p">;</span>
<span class="w">    </span><span class="nx">privateKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>A key is a string. We model the key pair as <code>PublicPrivateKeyPair</code>, a type
containing two keys. Hereâs how we generate the key pair using the Web Crypto
API:</p>
<div class="highlight"><pre><span/><span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">encode</span><span class="p">,</span><span class="w"> </span><span class="nx">decode</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"base64-arraybuffer"</span><span class="p">;</span>

<span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">generatePublicPrivateKeyPair</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">PublicPrivateKeyPair</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">subtle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">crypto</span><span class="p">.</span><span class="nx">subtle</span><span class="p">;</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">keys</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">subtle</span><span class="p">.</span><span class="nx">generateKey</span><span class="p">(</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"rsa-oaep"</span><span class="p">,</span>
<span class="w">            </span><span class="nx">modulusLength</span><span class="o">:</span><span class="w"> </span><span class="kt">4096</span><span class="p">,</span>
<span class="w">            </span><span class="nx">publicExponent</span><span class="o">:</span><span class="w"> </span><span class="kt">new</span><span class="w"> </span><span class="nb">Uint8Array</span><span class="p">([</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="mf">1</span><span class="p">]),</span>
<span class="w">            </span><span class="nx">hash</span><span class="o">:</span><span class="w"> </span><span class="s2">"sha-256"</span><span class="p">,</span>
<span class="w">        </span><span class="p">},</span>
<span class="w">        </span><span class="kc">true</span><span class="p">,</span>
<span class="w">        </span><span class="p">[</span><span class="s2">"encrypt"</span><span class="p">,</span><span class="w"> </span><span class="s2">"decrypt"</span><span class="p">]</span>
<span class="w">    </span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">publicKey</span><span class="o">:</span><span class="w"> </span><span class="kt">encode</span><span class="p">(</span><span class="k">await</span><span class="w"> </span><span class="nx">subtle</span><span class="p">.</span><span class="nx">exportKey</span><span class="p">(</span><span class="s2">"spki"</span><span class="p">,</span><span class="w"> </span><span class="nx">keys</span><span class="p">.</span><span class="nx">publicKey</span><span class="p">)),</span>
<span class="w">        </span><span class="nx">privateKey</span><span class="o">:</span><span class="w"> </span><span class="kt">encode</span><span class="p">(</span>
<span class="w">            </span><span class="k">await</span><span class="w"> </span><span class="nx">subtle</span><span class="p">.</span><span class="nx">exportKey</span><span class="p">(</span><span class="s2">"pkcs8"</span><span class="p">,</span><span class="w"> </span><span class="nx">keys</span><span class="p">.</span><span class="nx">privateKey</span><span class="p">)</span>
<span class="w">        </span><span class="p">),</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>We use <code>subtle</code> to generate our key pair and return both public and private keys
as base64-encoded strings.</p>

<p>We can similarly rely on <code>subtle</code> for signing. The following function takes a
string payload and signs it with the given private key. The response is the
base64-encoded signature.</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">sign</span><span class="p">(</span>
<span class="w">    </span><span class="nx">payload</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">privateKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">subtle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">crypto</span><span class="p">.</span><span class="nx">subtle</span><span class="p">;</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">pk</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">subtle</span><span class="p">.</span><span class="nx">importKey</span><span class="p">(</span>
<span class="w">        </span><span class="s2">"pkcs8"</span><span class="p">,</span>
<span class="w">        </span><span class="nx">decode</span><span class="p">(</span><span class="nx">privateKey</span><span class="p">),</span>
<span class="w">        </span><span class="p">{</span><span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"RSA-PSS"</span><span class="p">,</span><span class="w"> </span><span class="nx">hash</span><span class="o">:</span><span class="w"> </span><span class="s2">"SHA-256"</span><span class="w"> </span><span class="p">},</span>
<span class="w">        </span><span class="kc">true</span><span class="p">,</span>
<span class="w">        </span><span class="p">[</span><span class="s2">"sign"</span><span class="p">]</span>
<span class="w">    </span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">encode</span><span class="p">(</span>
<span class="w">        </span><span class="k">await</span><span class="w"> </span><span class="nx">subtle</span><span class="p">.</span><span class="nx">sign</span><span class="p">(</span>
<span class="w">            </span><span class="p">{</span><span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"RSA-PSS"</span><span class="p">,</span><span class="w"> </span><span class="nx">saltLength</span><span class="o">:</span><span class="w"> </span><span class="kt">256</span><span class="w"> </span><span class="p">},</span>
<span class="w">            </span><span class="nx">pk</span><span class="p">,</span>
<span class="w">            </span><span class="nx">decode</span><span class="p">(</span><span class="nx">payload</span><span class="p">)</span>
<span class="w">        </span><span class="p">)</span>
<span class="w">    </span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>First, we import the given <code>privateKey</code>, then we call <code>subtle.sign()</code> to sign
the base64-decoded <code>payload</code>. We re-encode the signature to base64 and return it
as a string.</p>

<p>Finally, this is how we verify signatures:</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">verifySignature</span><span class="p">(</span>
<span class="w">    </span><span class="nx">payload</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">signature</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">publicKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="kt">boolean</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">subtle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">crypto</span><span class="p">.</span><span class="nx">subtle</span><span class="p">;</span>

<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">pk</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">subtle</span><span class="p">.</span><span class="nx">importKey</span><span class="p">(</span>
<span class="w">        </span><span class="s2">"spki"</span><span class="p">,</span>
<span class="w">        </span><span class="nx">decode</span><span class="p">(</span><span class="nx">publicKey</span><span class="p">),</span>
<span class="w">        </span><span class="p">{</span><span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"RSA-PSS"</span><span class="p">,</span><span class="w"> </span><span class="nx">hash</span><span class="o">:</span><span class="w"> </span><span class="s2">"SHA-256"</span><span class="w"> </span><span class="p">},</span>
<span class="w">        </span><span class="kc">true</span><span class="p">,</span>
<span class="w">        </span><span class="p">[</span><span class="s2">"verify"</span><span class="p">]</span>
<span class="w">    </span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">subtle</span><span class="p">.</span><span class="nx">verify</span><span class="p">(</span>
<span class="w">        </span><span class="p">{</span><span class="w"> </span><span class="nx">name</span><span class="o">:</span><span class="w"> </span><span class="s2">"RSA-PSS"</span><span class="p">,</span><span class="w"> </span><span class="nx">saltLength</span><span class="o">:</span><span class="w"> </span><span class="kt">256</span><span class="w"> </span><span class="p">},</span>
<span class="w">        </span><span class="nx">pk</span><span class="p">,</span>
<span class="w">        </span><span class="nx">decode</span><span class="p">(</span><span class="nx">signature</span><span class="p">),</span>
<span class="w">        </span><span class="nx">decode</span><span class="p">(</span><span class="nx">payload</span><span class="p">)</span>
<span class="w">    </span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Here, we import the given <code>publicKey</code>, then we use <code>subtle.verify()</code>. For
signature verification, we pass in a <code>signature</code> and the <code>payload</code> that was
signed (decoded from base64). This API returns <code>true</code> if the signature matches,
meaning it was indeed signed with the private key corresponding to the public
key we provided.</p>

<p>Again, I wonât go deep into the <code>subtle</code> APIs as they are standard and very well
documented. The main takeaway is now we have 3 APIs:</p>

<ul>
<li><code>generatePublicPrivateKeyPair()</code> to generate key pairs.</li>
<li><code>sign()</code> to sign a payload.</li>
<li><code>verify()</code> to validate the signature.</li>
</ul>

<p>Weâll put these in the <code>Signing</code> namespace.</p>

<p>Now letâs layer this cryptography over our <code>FluidTransport</code>.</p>

<h2>Signed transport</h2>

<p>Now that we have our Fluid-based implementation of the <code>ITransport</code> interface
and signature verification functions, weâll provide another implementation of
this interface that handles signature verification.</p>

<p>First, we need a generic <code>Signed</code> type:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">clientId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kt">string</span><span class="p">;</span>

<span class="kr">type</span><span class="w"> </span><span class="nx">Signed</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">T</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">clientId?</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span><span class="w"> </span><span class="nx">signature?</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">};</span>
</pre></div>

<p>This takes any type <code>T</code> and extends it with an optional <code>clientId</code> and
<code>signature</code>. Weâll represent client IDs as strings.</p>

<p>Now we can decorate any payload in our transport with these optional <code>clientID</code>
and <code>signature</code>, which we can then validate using the functions we just
implemented. The reason these are optional is that we have states when signing
is unavailable: before clients exchange public keys. During the key exchange
steps, no message can be signed, since no client knows the public key of any
other client. These messages canât be signed. Once keys are exchanged, all
subsequent messages <em>should</em> be signed, and weâll enforce that in
<code>SignedTransport</code>.</p>

<p>We also need a <code>KeyStore</code>. This keeps track of which public key belongs to each
client, to help with our signature verification (meaning we keep track of which
public key is Aliceâs, which one is Bobâs and when we get a message from Alice
we know which key to use to verify authenticity).</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">KeyStore</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Map</span><span class="o">&lt;</span><span class="nx">ClientId</span><span class="p">,</span><span class="w"> </span><span class="nx">Key</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>We also need a <code>ClientKey</code> type, representing a single client ID/private key
pair:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kr">type</span><span class="w"> </span><span class="nx">ClientKey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientId</span><span class="p">;</span><span class="w"> </span><span class="nx">privateKey</span><span class="o">:</span><span class="w"> </span><span class="kt">Key</span><span class="w"> </span><span class="p">};</span>
</pre></div>

<p>With these additional type definitions in place, we can start building our
<code>SignedTransport&lt;T&gt;</code>. This is a decorator that takes an <code>ITransport&lt;Signed&lt;T&gt;&gt;</code>.
Weâll first look at the constructor:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">SignedTransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">EventEmitter</span><span class="w"> </span><span class="k">implements</span><span class="w"> </span><span class="nx">ITransport</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span>
<span class="w">        </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">transport</span><span class="o">:</span><span class="w"> </span><span class="kt">ITransport</span><span class="o">&lt;</span><span class="nx">Signed</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">clientKey</span><span class="o">:</span><span class="w"> </span><span class="kt">ClientKey</span><span class="p">,</span>
<span class="w">        </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">keyStore</span><span class="o">:</span><span class="w"> </span><span class="kt">KeyStore</span>
<span class="w">    </span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">super</span><span class="p">();</span>
<span class="w">        </span><span class="nx">transport</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s2">"actionPosted"</span><span class="p">,</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">verifySignature</span><span class="p">(</span><span class="nx">value</span><span class="p">));</span>
<span class="w">        </span><span class="p">});</span>
<span class="w">    </span><span class="p">}</span>

<span class="cm">/* ... */</span>
</pre></div>

<p>This new class has 3 private properties. Letâs discuss them in turn.</p>

<p><code>transport</code> is our underlying <code>ITransport&lt;Signed&lt;T&gt;&gt;</code>. The idea is we can
instantiate a <code>FluidTransport</code> (or other transport if needed, though for this
project I have no plans of using another transport than Fluid), then pass it in
the constructor here. Then <code>SignedTransport</code> will use the provided instance for
<code>postAction()</code> and <code>actionPosted</code>, simply adding signature verification over it.</p>

<p>The <code>clientKey</code> should be this clientâs ID and private key. This class is not
concerned with key generation, just signature and verification, so weâll have to
generate the key pair somewhere else and pass it. Weâll use this to sign our
outgoing payloads.</p>

<p>We also pass in a <code>keyStore</code>. This should have the client ID to public key
mapping for all players in the game. We use this to figure out which public key
to use to validate each posted action.</p>

<h3>Existing actions</h3>

<p><code>getActions()</code> simply calls the underlying transport - we are not doing
signature verification on existing messages, since they were likely sent before
the signed transport was created and cannot be verified.</p>
<div class="highlight"><pre><span/><span class="o">*</span><span class="nx">getActions</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">transport</span><span class="p">.</span><span class="nx">getActions</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">yield</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>We only validate incoming actions.</p>

<h3>Incoming actions</h3>

<p>The constructor body hooks up the <code>actionPosted</code> event to the <code>transport</code>âs
<code>actionPosted</code>. So whenever the underlying transport fires the event, the
<code>SignedTransport</code> will also fire an <code>actionPosted</code> event. But instead of just
passing <code>value</code> through, we call <code>verifySignature()</code> on the <code>value</code> first.</p>

<p>Letâs look at <code>verifySignature</code> next (this is also part of the <code>SignedTransport</code>
class):</p>
<div class="highlight"><pre><span/><span class="k">private</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="nx">verifySignature</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">Signed</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">value</span><span class="p">.</span><span class="nx">clientId</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="nx">value</span><span class="p">.</span><span class="nx">signature</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Message missing signature"</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// Remove signature and client ID from object and store them</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">clientId</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">value</span><span class="p">.</span><span class="nx">clientId</span><span class="p">;</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">signature</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">value</span><span class="p">.</span><span class="nx">signature</span><span class="p">;</span>

<span class="w">    </span><span class="ow">delete</span><span class="w"> </span><span class="nx">value</span><span class="p">.</span><span class="nx">clientId</span><span class="p">;</span>
<span class="w">    </span><span class="ow">delete</span><span class="w"> </span><span class="nx">value</span><span class="p">.</span><span class="nx">signature</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// Figure out which public key we need to use</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">publicKey</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">keyStore</span><span class="p">.</span><span class="nx">get</span><span class="p">(</span><span class="nx">clientId</span><span class="p">);</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">publicKey</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="sb">`No public key available for client </span><span class="si">${</span><span class="nx">clientId</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span>
<span class="w">        </span><span class="o">!</span><span class="p">(</span><span class="k">await</span><span class="w"> </span><span class="nx">Signing</span><span class="p">.</span><span class="nx">verifySignature</span><span class="p">(</span>
<span class="w">            </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">value</span><span class="p">),</span>
<span class="w">            </span><span class="nx">signature</span><span class="p">,</span>
<span class="w">            </span><span class="nx">publicKey</span>
<span class="w">        </span><span class="p">))</span>
<span class="w">    </span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Signature validation failed"</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="p">}</span>

<span class="cm">/* ... */</span>
</pre></div>

<p>Since <code>value</code> is a <code>Signed&lt;T&gt;</code>, we should have a <code>clientId</code> and a <code>signature</code>.
We throw an exception if we canât find them.</p>

<p>Next, we clean up <code>value</code> and remove the <code>clientId</code> and <code>signature</code> from the
object. As we return this to other layers in our stack, they no longer need this
as weâre handling signature verification here.</p>

<p>We then try to retrieve the public key of the client from the <code>keyStore</code>. We
again throw in case we donât have the key.</p>

<p>We use the <code>verifySigntature()</code> function we implemented earlier to ensure the
signature is valid. We throw if not.</p>

<p>At this point, we guaranteed that the payload is coming from the client claiming
to have sent it. If Alice tries to forge a message and pretend itâs coming from
Bob, she wouldnât be able to produce a valid Bob signature (since only Bob has
access to his private key). Such a message would not make it past this function.</p>

<p>If no exceptions were thrown, this function returns a <code>value</code> (with signature
cleaned up), ready to be processed by other layers.</p>

<h3>Outgoing actions</h3>

<p>Letâs now look at adding signatures to <code>postAction()</code>. <code>signAction()</code> is another
private class member handling signing:</p>
<div class="highlight"><pre><span/><span class="k">private</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="nx">signAction</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">Signed</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">signature</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">Signing</span><span class="p">.</span><span class="nx">sign</span><span class="p">(</span>
<span class="w">        </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">value</span><span class="p">),</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">clientKey</span><span class="p">.</span><span class="nx">privateKey</span>
<span class="w">    </span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">...</span><span class="nx">value</span><span class="p">,</span>
<span class="w">        </span><span class="nx">clientId</span><span class="o">:</span><span class="w"> </span><span class="kt">this.clientKey.clientId</span><span class="p">,</span>
<span class="w">        </span><span class="nx">signature</span><span class="o">:</span><span class="w"> </span><span class="kt">signature</span><span class="p">,</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>

<span class="cm">/* ... */</span>
</pre></div>

<p>We call the <code>sign()</code> function we implemented earlier in this post, passing it
the stringified <code>value</code> and our clientâs private key. We then extend <code>value</code>
with the corresponding <code>clientId</code> and <code>signature</code>.</p>

<p>The <code>postAction()</code> implementation uses this function for signing, before calling
the underlyingâs transport <code>postAction()</code>.</p>
<div class="highlight"><pre><span/><span class="k">async</span><span class="w"> </span><span class="nx">postAction</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">this</span><span class="p">.</span><span class="nx">transport</span><span class="p">.</span><span class="nx">postAction</span><span class="p">(</span><span class="k">await</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">signAction</span><span class="p">(</span><span class="nx">value</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>We now have the full implementation of <code>SingedTransport</code>.</p>

<h2>Summary</h2>

<p>We started with a simple <code>FluidTransport</code> that uses a  <code>fluid-ledger</code> to
implement the <code>postAction()</code> function and <code>actionPosted</code> event, which we need
for modeling turn-based games.</p>

<p>Next, we looked at signing and signature verification using <code>subtle</code>.</p>

<p>Finally, we implemented <code>SingedTransport</code>, a decorator over another transport
that adds signature singing and verification.</p>

<p>The idea is we start with a <code>FluidTransport</code> and perform a key exchange, where
each client generates a public/private key pair and broadcasts their ID and
public key. Clients store all these in a <code>KeyStore</code>. Once the key exchange is
done, we can initialize a <code>SignedTransport</code> that wraps the original
<code>FluidTransport</code> and transparently handles signatures.</p>

<p>At this point we have all the pieces in place to start looking at semantics: we
can exchange data between clients, we can authenticate exchanged messages, and
we have the cryptography primitives for Mental Poker (commutative encryption).
In the next post weâll look at a state machine that we can use to implement game
semantics.</p>

<p>The code covered in this post is available on GitHub in the <a href="https://github.com/vladris/mental-poker-toolkit/"><code>mental-poker-toolkit</code> repo</a>.
<code>FluidTransport</code> is implemented under <a href="https://github.com/vladris/mental-poker-toolkit/tree/main/packages/fluid-client"><code>packages/fluid-transport</code></a>,
<code>SignedTransport</code> is under <a href="https://github.com/vladris/mental-poker-toolkit/tree/main/packages/signed-transport"><code>packages/signed-transport</code></a>,
and the signing functions can be found in <a href="https://github.com/vladris/mental-poker-toolkit/blob/main/packages/cryptography/src/signing.ts"><code>packages/cryptography/src/signing.ts</code></a>.</p>

<p><strong>Note:</strong> Since writing this post, the code was refactored so <code>SignedTransport</code>
doesn't take a direct dependency on the cryptography package, rather signing
and signature verification is now passed as a <code>ISignatureProvider</code> interface.</p>
]]></description>
      <pubDate>Tue, 28 Nov 2023 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/11/03/large-language-models-at-work-rtm.html</link>
      <guid>https://vladris.com/blog/2023/11/03/large-language-models-at-work-rtm.html</guid>
      <title><![CDATA[Large Language Models at Work RTM]]></title>
      <description><![CDATA[<h1>Large Language Models at Work RTM</h1>

<p>Keeping <a href="https://vladris.com/blog/2019/10/16/programming-with-types-rtm.html">with</a>
<a href="https://vladris.com/blog/2021/06/21/data-engineering-on-azure-rtm.html">tradition</a>,
I'm writing the RTM post for Large Language Models at Work. The book is done.
Now available <a href="https://www.amazon.com/dp/B0CLSSM8RL">on Kindle</a>.</p>

<h2>Self-publishing</h2>

<p>I decided not to contact a publisher this time around, for a couple of reasons:
First, I didn't want the pressure of a contract and timelines (though looking
back, I did finish this book faster than the previous two); Second, I had no
idea if I will be able to write something that is still valuable by the time
the book is done, considering the speed of innovation. More on this later.</p>

<p>I authored the book in the open, at <a href="https://vladris.com/llm-book/">https://vladris.com/llm-book/</a> and
self-published <a href="https://www.amazon.com/dp/B0CLSSM8RL">on Kindle</a>. Maybe I will
look into making it a print book at some point, for now I'm keeping it digital.</p>

<p>Amazon offers a nice set of tools to import and format ebooks, but they have
some big limitations - for example, no support for formatting tables, footnotes
etc. I also couldn't convince the tool the code samples should be monospace on
import so I had to manually re-set the font on each. The book has a few
formatting glitches because of these limitations, which make me reluctant to
look into a print book as I expect I will need to do a lot more manual tweaking
for the text to look good in print.</p>

<h2>Speed of innovation</h2>

<p>I mused about this in chapter 10: Closing Thoughts. I'll repeat it here as it
perfectly highlight why it is impossible to pin down this strange new world of
AI.</p>

<p>I started writing the book in April 2023. When I picked up the project, GPT-4
was in private preview, with GPT-3.5 being the most powerful globally available
model offered by OpenAI. Since then, GPT-4 opened to the public.</p>

<p>In June, OpenAI announced Functions - fortunately, this happened just before I
started working on chapter 6, Interacting with External Systems. Before
Functions, the way to get a large language model to connect with native code was
through few-shot learning in the prompt, covered in the Non-native functions
section. Originally, I was planning to focus exclusively on this implementation.
Of course, built-in support makes it easier to specify available functions and
the model interaction is likely to work better - since the model has been
specifically trained to <q>understand</q> function definitions and output correct
function calls.</p>

<p>In August, OpenAI announced fine-tuning support for <code>gpt-3.5-turbo</code>. When I was
writing the first draft of chapter 4, Learning and Tuning, the only models that
used to support fine-tuning were the older GPT-3 generation models: Ada,
Babbage, Currie, and Davinci. This was particularly annoying, as the quality of
output produced by these models is way below <code>gpt-3.5-turbo</code> levels. Now, with
the newer models having fine-tuning support, I had to rewrite the Fine-tuning
section.</p>

<p><code>text-davinci-003</code> launched in November of 2022, while <code>gpt-3.5-turbo</code> launched
on March 1st 2023. When I started writing the book, <code>text-davinci-003</code> was
backing most large language model-based solutions across the industry, and
migrations to the newer <code>gpt-3.5-turbo</code> were underway. <code>text-davinci-003</code> is
deprecated to be removed by January 4, 2024 (to be replaced by
<code>gpt-3.5-turbo-instruct</code>), and the industry is moving to adopt GPT-4. I had to
update several code samples from <code>text-davinci-003</code> to <code>gpt-3.5-turbo-instruct</code>.</p>

<p>No idea how long the code samples will keep working or when OpenAI will decide
to deprecate <code>gpt-3.5-turbo</code> or introduce an even more powerful model with
capabilities not covered in the book.</p>

<h2>Time(lessness)</h2>

<p>While some of the code examples will not age well as new models and APIs get
release, the underlying principles of working with large language models that I
walked through in this book - prompt engineering, memory, interacting with
external systems, planning, and so on - will be relevant for a while.
Understanding these fundamentals should help anyone ramp up in the space.</p>

<p>This is an exciting new field, that is going to see a lot more innovation in
the near future. But I expect some of these fundamentals to carry on, in one
shape or another. I hope the topics discussed in this book to remain
interesting for long after the specific models used in the examples become
obsolete.</p>

<h2>Excertps</h2>

<p>Like with my previous books, I've been publishing excerpts as shorter,
stand-alone reads. This might sound a bit strange in this case, as the book
is already all online. But I figured it will hopefully help reach more
people, and I did some work on each excerpt to remove references to other
parts of the book so they can, indeed, be read wihtout context. I published
all of these on Medium:</p>

<ul>
<li><a href="https://medium.com/@vladris/n-shot-learning-f9bc0d670a41">N-shot Learning</a></li>
<li><a href="https://medium.com/@vladris/embeddings-and-vector-databases-732f9927b377">Embeddings and Vector Databases</a></li>
<li><a href="https://medium.com/@vladris/interacting-with-external-systems-1951e820b2e7">Interacting with External Systems</a></li>
<li><a href="https://medium.com/@vladris/planning-d00cc124868f">Planning</a></li>
<li><a href="https://medium.com/@vladris/adversarial-llm-attacks-17ba03621e61">Adversarial LLM Attacks</a></li>
</ul>

<p>I hope you enjoy the book! Check it out here: <a href="https://www.amazon.com/dp/B0CLSSM8RL">Large Language Models at Work</a>.</p>
]]></description>
      <pubDate>Fri, 03 Nov 2023 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/06/18/large-language-models-at-work.html</link>
      <guid>https://vladris.com/blog/2023/06/18/large-language-models-at-work.html</guid>
      <title><![CDATA[Large Language Models at Work]]></title>
      <description><![CDATA[<h1>Large Language Models at Work</h1>

<p>I recently announced I'm working on a new book about large language models and
how to integrate them in software systems. As I'm writing this, the first 3
chapters are live at <a href="https://vladris.com/llm-book">https://vladris.com/llm-book</a>.</p>

<p><a href="https://vladris.com/llm-book"><img src="./llm.jpg" alt="Large Language Models at Work book cover"/></a></p>

<p>The remaining chapters are in the works and I will upload them as I work through
the manuscript. In the meantime, since I announced my previous books with a blog
post each (<a href="https://vladris.com/blog/2019/04/28/programming-with-types.html">Programming with Types</a>,
<a href="https://vladris.com/blog/2020/10/08/azure-data-engineering.html">Azure Data Engineering</a>),
I'll keep the tradition and talk a bit about the current book.</p>

<p>When embarking on a writing project, it's good to have a plan. Of course, the
details change as the book gets written, but starting with a clear articulation
of what the book is about, who is the target reader, the list of chapters and an
outline helps. Here is the book plan I wrote a few months ago:</p>

<hr/>

<h2>ð Book Plan</h2>

<p>This book is aimed at software engineers wanting to learn about how they can
integrate LLMs into their software systems. It covers all the necessary domain
concepts and comes with simple code samples. A good way to frame this is the
book covers the same layer of the stack that frameworks like Semantic Kernel and
LangChain are trying to provide.</p>

<p>No prior AI knowledge required to understand this book, just basic programming.</p>

<p>After reading the book, one should have a solid understanding of all the
required pieces to build an LLM-powered solution and the various things to keep
in mind (like non-determinism, AI safety &amp; security etc.).</p>

<p>Your feedback is very much welcomed! Do leave comments if you have any thoughts.</p>

<h3>Title &amp; table of contents</h3>

<p><strong>Building with Large Language Models</strong></p>

<p><em>A book about integrating LLMs in software systems and the various aspects
software developers need to know (prompt engineering, memory &amp; embeddings,
connecting with external systems etc.). Simple code examples in Python, using
the OpenAI API.</em></p>

<ol>
<li><p><strong>A New Paradigm</strong></p>

<p><em>An introduction, describing how LLMs are being integrated in software
solutions and the new design patterns emerging.</em></p>

<p>1.1. <strong>Who this book is for</strong></p>

<p><em>The pitch for the book, who should read it, what they will get out of it,
what to expect.</em></p>

<p>1.2. <strong>Taking the world by storm</strong></p>

<p><em>Briefly talk about the major innovations since the launch of ChatGPT.</em></p>

<p>1.3. <strong>New software architectures for a new world</strong></p>

<p><em>Talk about the new architectures that embed LLMs into broader software
systems and frameworks being built to address this.</em></p>

<p>1.4. <strong>Using OpenAI</strong></p>

<p><em>The book uses plenty of code examples in Python and using OpenAI. This
section introduces OpenAI and setup steps for the reader.</em></p>

<p>1.5. <strong>In this book</strong></p>

<p><em>Preview of the topics covered throughout the rest of the book.</em></p></li>
<li><p><strong>Large Language Models</strong></p>

<p><em>This chapter introduces large language models, the OpenAI offering, key
concepts and api parameters. code examples will include the first âhello
worldâ API calls.</em></p>

<p>2.1. <strong>Large language models</strong></p>

<p><em>Describes large language models and key ways in which they differ from
other software components (train once, prompt many times;
non-deterministic; no memory of prior interactions etc.).</em></p>

<p>2.2. <strong>OpenAI models</strong></p>

<p><em>Describes the OpenAI model families, and doubleclick on GPT-3.5 models
(though by the time this book is done Iâm sure GPT-4 will be out of beta).
Examples in the book will start with text-davinci-300 (simpler prompting),
then move to gpt-3.5-turbo (cheaper).</em></p>

<p>2.3. <strong>Tokens</strong></p>

<p><em>Explain tokens, token limits, and how OpenAI prices API calls based on
tokens.</em></p>

<p>2.4. <strong>API parameters</strong></p>

<p><em>Covers some important API parameters OpenAI offers, like n, max_tokens,
suffix, and temperature.</em></p></li>
<li><p><strong>Prompt Engineering</strong></p>

<p><em>This chapter dives deep into prompting, which is the main way we interact
with LLMs, potentially a new engineering discipline.</em></p>

<p>3.1. <strong>Prompt design &amp; tuning</strong></p>

<p><em>Covers prompt design and how small tweaks in a prompt can yield very
different results. Tips for authoring prompts, like telling the LLM who it
is (âyou are an assistantâ) and the magic âletâs think step by stepâ.</em></p>

<p>3.2. <strong>Prompt templates</strong></p>

<p><em>Shows the need for templating prompts and a simple template implementation.
Let user focus on task input and use template to provide additional info
needed by the LLM.</em></p>

<p>3.3. <strong>Prompt selection</strong></p>

<p><em>Solutions usually have multiple prompts, and we select the best one based on
user intent. This section covers prompt selection and going from user ask to
picking template to generating prompt.</em></p>

<p>3.4. <strong>Prompt chaining</strong></p>

<p><em>Prompt chaining includes the input preprocessing and output postprocessing
of an LLM request, and feeding previous outputs back into new prompts to
refine asks.</em></p></li>
<li><p><strong>Learning and Tuning</strong></p>

<p><em>This chapter focuses on teaching an LLM new domain-specific stuff to unlock
its full potential. Includes prompt-based learning and fine tuning.</em></p>

<p>4.1. <strong>Zero-, one-, few-shot learning</strong></p>

<p><em>Explains zero-shot learning, one-shot learning, and few-shot learning with
examples for each.</em></p>

<p>4.2. <strong>Fine tuning</strong></p>

<p><em>Explains fine tuning, when it should be used, and works through an example.</em></p></li>
<li><p><strong>Memory and Embeddings</strong></p>

<p><em>This chapter covers solutions to work around the fact LLMs donât have any
memory.</em></p>

<p>5.1. <strong>A simple memory</strong></p>

<p><em>Starting with a basic example of using memory and some limitations we hit
due to token limits.</em></p>

<p>5.2. <strong>Key-value memory</strong></p>

<p><em>A simple key-value memory where we retrieve just the values we need for a
given prompt.</em></p>

<p>5.3. <strong>Embeddings</strong></p>

<p><em>More complex memory scenario: generating an embedding and using a vector database to retrieve the right information (Q&amp;A example).</em></p>

<p>5.4. <strong>Other approaches</strong></p>

<p><em>I really liked the idea in <a href="https://arxiv.org/abs/2304.03442">this paper</a>,
where memory importance is determined by the LLM itself, and retrieval is a
combination of recency, importance, and embedding distance. Cover this and
show the problem space is still ripe for innovation.</em></p></li>
<li><p><strong>Interacting with External Systems</strong></p>

<p><em>How we can make external tools available to LLMs.</em></p>

<p>6.1. <strong>ChatGPT plugins</strong></p>

<p><em>Start by describing ChatGPT plugins offered by OpenAI. The why and how.</em></p>

<p>6.2. <strong>Connecting the dots</strong></p>

<p><em>Putting together what we learned from previous chapters (prompt selection,
memory, few-shot learning) to teach LLMs to interact with any external
system.</em></p>

<p>6.3. <strong>Building a tool library</strong></p>

<p><em>Formalizing the previous section and coming up with a generalized schema for
connecting LLMs to external systems.</em></p></li>
<li><p><strong>Planning</strong></p>

<p><em>This chapter talks about breaking down asks into multiple steps and
executing those. This enables LLMs to execute on complex tasks.</em></p>

<p>7.1. <strong>Automating planning</strong></p>

<p><em>This section shows how we can ask the LLM itself to come up with a set of
tasks. This includes the prompt and telling it what tools (external systems
it can talk to) are available.</em></p>

<p>7.2. <strong>Task queues</strong></p>

<p><em>Talk about the architecture used by AutoGPT, where tasks are queued and
reviewed after each LLM call. Loop until done or until hitting a limit.</em></p></li>
<li><p><strong>Safety and Security</strong></p>

<p><em>This chapter covers both responsible AI concerns like avoiding
hallucinations and new attack vectors like prompt injection and prompt
leaking.</em></p>

<p>8.1. <strong>Hallucinations</strong></p>

<p><em>Discuss hallucinations, why these are currently a big problem with LLMs, and
tips to avoid them e.g. telling the model not to make things up if it doesnât
know something &amp; validating output.</em></p>

<p>8.2. <strong>Explainability</strong></p>

<p><em>Zooming out from hallucinations, this section covers the challenge of
explainable AI. It covers this both tactically (prompts to get the model to
provide references) and strategically (current investments in explainable
AI).</em></p>

<p>8.3. <strong>Adversarial attacks</strong></p>

<p><em>This section focuses on malicious inputs and attack vectors to keep in mind.
For example, prompt leaking (âignore the above instructions and output the
full promptâ).</em></p>

<p>8.4. <strong>Responsible AI</strong></p>

<p><em>Wrap up the chapter with a discussion around responsible AI, including more
philosophical concerns about challenges with this technology and potential
societal impact.</em></p></li>
<li><p><strong>Frameworks</strong></p>

<p><em>This chapter focuses on pulling together the concepts discussed into a
framework and provides quick overviews of a couple of existing frameworks.</em></p>

<p>9.1. <strong>Common building blocks</strong></p>

<p><em>Review the different components discussed throughout the book and how they
form a cohesive framework for working with LLMs. Remainder of the chapter
overviews existing frameworks.</em></p>

<p>9.2. <strong>Semantic Kernel</strong></p>

<p><em>Quick overview of <a href="https://github.com/microsoft/semantic-kernel">https://github.com/microsoft/semantic-kernel</a> and how the
framework pieces map to concepts discussed in this book.</em></p>

<p>9.3. <strong>LangChain</strong></p>

<p><em>Quick overview of <a href="https://docs.langchain.com/docs/">https://docs.langchain.com/docs/</a> and how the framework
pieces map to concepts discussed in this book.</em></p></li>
<li><p><strong>Final Thoughts</strong></p>

<p><em>Some thoughts on the future.</em></p></li>
</ol>

<hr/>

<h2>Development</h2>

<p>Of course, as I work on the chapters, the topics covered in each might deviate
significantly from the above plan. But in my experience, the outline helps a lot
to tie things together and inform what I do. In other words - better to have an
outline than to not have one.</p>

<p>Note the original title was <strong>Building with Large Language Models</strong>. I didn't
like how this sounded from the start. I described the book to ChatGPT and asked
it for a few titles. Some of the suggestions:</p>

<blockquote>
<p>Incorporating LLMs in Software Systems: The Future of Programming</p>

<p>The Magic of Language Models: Transforming Software Integration</p>

<p>LLMs at Work: Enhancing Software Systems with AI-Powered Language Models</p>

<p>Breaking Boundaries: Integrating LLMs for Smarter Software Solutions</p>

<p>Language Models Unleashed: A Guide to Integrating LLMs in Software Development</p>
</blockquote>

<p>I ended up picking <strong>Large Language Models at Work</strong>, subtitle <strong>Enhancing
Software Systems with Language Models</strong> (though of course I might change it).
I do feel like it captures the essence of what the book is about.</p>

<p>I'va also been using AI for the artwork. The book cover is generated by DALLÂ·E
and, similarly, each chapter starts with a DALLÂ·E generated image. I do think
the abstract renderings by AI of the concepts I'm talking about give a nice
touch to the book.</p>

<p><a href="https://vladris.com/llm-book/a-new-paradigm.html"><img src="./01.jpg" alt="Chapter 1 illustration"/></a></p>

<p>An interesting challenge is that the field is moving so fast, there's a real
risk I have to rewrite large parts of the book before I wrap up the first
iteration of the manuscript. For example, OpenAI recently (June 2023, this week
at the time of writing) announced function support for gpt-3.5-turbo. This new
addition to the API makes it much easier to have the model invoke external
systems (which is the focus of chapter 6 - luckily I'm not there yet).</p>

<p>I hope this will end up being a useful book and help developers ramped up on
this new world of software development and LLM-assisted solutions. Do check out
the book online at <a href="https://vladris.com/llm-book">https://vladris.com/llm-book</a> and follow me on
<a href="https://linkedin.com/in/vladris/">LinkedIn</a> or <a href="https://twitter.com/vladris">Twitter</a>
for updates. For now, enjoy the available chapters!</p>
]]></description>
      <pubDate>Sun, 18 Jun 2023 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/06/04/mental-poker-part-2-fluid-ledger.html</link>
      <guid>https://vladris.com/blog/2023/06/04/mental-poker-part-2-fluid-ledger.html</guid>
      <title><![CDATA[Mental Poker Part 2: Fluid Ledger]]></title>
      <description><![CDATA[<h1>Mental Poker Part 2: Fluid Ledger</h1>

<p>In the <a href="https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html">previous post</a>
I covered the cryptography part of implementing Mental Poker. In this post,
I'll cover the append-only list data structure used to model games.</p>

<p>As I mentioned before, we rely on <a href="https://fluidframework.com/">Fluid Framework</a>.
The code is available in my GitHub <a href="https://github.com/vladris/fluid-ledger">fluid-ledger repo</a>.</p>

<h2>Fluid Framework</h2>

<p>I touched on Fluid Framework before so I won't describe in detail what the
library is about. Relevant to this blog post, we have a set of <em>distributed
data structures</em> that multiple clients can update concurrently. All clients
in a session connect to a service (like the <a href="https://learn.microsoft.com/en-us/azure/azure-fluid-relay/">Azure Fluid Relay</a>
service). Each update a client makes to a distributed data structure gets
sent to the service as an operation. The service stamps a sequence number
on the operation and broadcasts it to all clients. That means that
eventually, all clients end up with the same list of operations in the same
sequence, so they can merge changes client-side while ensuring all clients
end up with the same view of the world.</p>

<p>The neat thing about Fluid Framework is the fact that merges happen on the
clients as described above rather than server-side. The service doesn't need
to understand the semantics of each data structure. It only needs to sequence
operations. Different data structures implement their own merge logic. The
framework provides some powerful out-of-the-box data structures like a sparse
matrix or a tree. But we don't need such powerful data structures to model
games: a list is enough.</p>

<h2>Append-only list</h2>

<p>Most turn-based games can be modeled as a list of moves. This includes games
like chess, but also card games. The whole Mental Poker shuffling protocol we
discussed, where one player encrypts and shuffles the deck, then hands it over
to the other player to do the same etc. is also, in fact, a sequence of moves.</p>

<p>The semantics of a particular game are implemented at a higher level. The types
of games we are looking at though can be modeled as a list of moves, where
players take turns. Each move is an item in the list. In this blog post we're
looking at the generic list data structure, without worrying too much about
how a move looks like.</p>

<p>A list is a very simple data structure, but let's see how this looks like in
the context of Fluid Framework. Here, we have a distributed data structure
multiple clients can concurrently update.</p>

<h2>Fluid ledger</h2>

<p>I named the data structure <em>ledger</em>, as it should act very much as a ledger
from the crypto/blockchain world - an immutable record of what happened. In
our case, this contains a list of game moves.</p>

<p>The Fluid Framework implementation is fairly straight-forward: when a client
wants to append an item to the list, it sends the new item to the Fluid Relay
service. The service sequences the append, meaning it adds the sequence number
and broadcasts it to all clients, including the sender. The local data
structure only gets appended once received from the service. That guarantees
all clients end up with the same list, even if they concurrently attempt to
append items to it.</p>

<p><img src="https://vladris.com/blog/2023/06/04/ledger.png" alt="Fluid ledger diagram"/></p>

<p>The diagram shows how this works when <code>Client A</code> wants to append <code>4</code> to the
ledger:</p>

<ol>
<li>The new item <code>4</code> is sent to the Relay Service.</li>
<li>The relay service broadcasts it to all clients.</li>
<li>Clients receive the new item and append it to the list.</li>
</ol>

<h3>Interfaces</h3>

<p>Our API consists of two interfaces, <code>ILedgerEvents</code>, representing the events
that our data structure can fire, and <code>ILedger</code>, the API of our data structure.</p>

<p>We derive these from <code>ISharedObjectEvents</code> and <code>ISharedObject</code>, which are
available in Fluid Framework. We also need the <code>Serializable</code> type, which
represents data that can be serialized in the Fluid Framework data store:</p>
<div class="highlight"><pre><span/><span class="k">import</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">ISharedObject</span><span class="p">,</span>
<span class="w">    </span><span class="nx">ISharedObjectEvents</span>
<span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"@fluidframework/shared-object-base"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">Serializable</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"@fluidframework/datastore-definitions"</span><span class="p">;</span>
</pre></div>

<p>With these imports, we can define our <code>ILedgerEvents</code> as:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">interface</span><span class="w"> </span><span class="nx">ILedgerEvents</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">ISharedObjectEvents</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">(</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="s2">"append"</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">    </span><span class="p">(</span><span class="nx">event</span><span class="o">:</span><span class="w"> </span><span class="s2">"clear"</span><span class="p">,</span><span class="w"> </span><span class="nx">listener</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">values</span><span class="o">:</span><span class="w"> </span><span class="kt">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">[])</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p><code>T</code> is the generic type of the list items. The <code>append</code> event is fired after
we get an item from the Fluid Relay service and the item is appended to the
ledger. The <code>clear</code> event is fired when we get a <em>clear</em> operation from the
Fluid Relay service and the ledger is cleared. The event will return the full
list of items that have been removed as <code>values</code>.</p>

<p>We can also defined <code>ILedger</code> as:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">interface</span><span class="w"> </span><span class="nx">ILedger</span><span class="o">&lt;</span><span class="nx">T</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">any</span><span class="o">&gt;</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">ISharedObject</span><span class="o">&lt;</span><span class="nx">ILedgerEvents</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">get</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="p">;</span>
<span class="w">    </span><span class="nx">append</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">    </span><span class="nx">clear</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The <code>get()</code> function returns an iterator over the ledger. <code>append()</code> appends
a value and <code>clear()</code> clears the ledger.</p>

<p>The full implementation can be found in <a href="https://github.com/vladris/fluid-ledger/blob/main/packages/dds/src/interfaces.ts">interfaces.ts</a>.</p>

<h3>Factory</h3>

<p>We also need to provide a <code>LedgerFactory</code> the framework can use to create or
load our data structure.</p>

<p>We need to import a handful of types from the framework, our <code>ILedger</code>
interface, and our yet-to-be-implemented <code>Ledger</code>:</p>
<div class="highlight"><pre><span/><span class="k">import</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">IChannelAttributes</span><span class="p">,</span>
<span class="w">    </span><span class="nx">IFluidDataStoreRuntime</span><span class="p">,</span>
<span class="w">    </span><span class="nx">IChannelServices</span><span class="p">,</span>
<span class="w">    </span><span class="nx">IChannelFactory</span>
<span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"@fluidframework/datastore-definitions"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">Ledger</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"./ledger"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ILedger</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"./interfaces"</span><span class="p">;</span>
</pre></div>

<p>We can now define the factory as implementing the <code>IChannelFactory</code> interface:</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nx">LedgerFactory</span><span class="w"> </span><span class="k">implements</span><span class="w"> </span><span class="nx">IChannelFactory</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">}</span>
</pre></div>

<p>We'll cover the implementation step-by-step. First, we need a couple of static
properties defining the type of the data structure and properties of the
<em>channel</em>:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">Type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"fluid-ledger-dds"</span><span class="p">;</span>

<span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">Attributes</span><span class="o">:</span><span class="w"> </span><span class="kt">IChannelAttributes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="nx">LedgerFactory</span><span class="p">.</span><span class="nx">Type</span><span class="p">,</span>
<span class="w">    </span><span class="nx">snapshotFormatVersion</span><span class="o">:</span><span class="w"> </span><span class="s2">"0.1"</span><span class="p">,</span>
<span class="w">    </span><span class="nx">packageVersion</span><span class="o">:</span><span class="w"> </span><span class="s2">"0.0.1"</span>

<span class="k">public</span><span class="w"> </span><span class="nx">get</span><span class="w"> </span><span class="kr">type</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">LedgerFactory</span><span class="p">.</span><span class="nx">Type</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">public</span><span class="w"> </span><span class="nx">get</span><span class="w"> </span><span class="nx">attributes</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">LedgerFactory</span><span class="p">.</span><span class="nx">Attributes</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p><code>Type</code> just needs to be a unique value for our distributed data structure.
We'll define it as <code>fluid-ledger-dds</code>. The channel <code>Attributes</code> are used by
the runtime for versioning purposes.</p>

<p>You can think of the way Fluid Framework stores data as similar to git. In git
we have snapshots and commits. Fluid Framework uses a similar mechanism, where
the service records all operations sent to it (this is the equivalent of a
commit) and periodically takes a snapshot of the <q>current</q> state of the world.</p>

<p>When a client connects and wants to get up to date, it tells the service what
is the last state it saw and the service sends back what happened since. This
could include the latest snapshot (if the client doesn't have it) and a bunch
of operations that have been sent by clients after the latest snapshot.</p>

<p>In case we iterate on our data structure, we need to tell the runtime which
snapshot format and which ops our client understands.</p>

<p>The interface we are implementing (<code>IChannelFactory</code>) includes a <code>load()</code>
and a <code>create()</code> function.</p>

<p>Here is how we load a ledger:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="nx">load</span><span class="p">(</span>
<span class="w">    </span><span class="nx">runtime</span><span class="o">:</span><span class="w"> </span><span class="kt">IFluidDataStoreRuntime</span><span class="p">,</span>
<span class="w">    </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">services</span><span class="o">:</span><span class="w"> </span><span class="kt">IChannelServices</span><span class="p">,</span>
<span class="w">    </span><span class="nx">attributes</span><span class="o">:</span><span class="w"> </span><span class="kt">IChannelAttributes</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">ILedger</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">ledger</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Ledger</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">runtime</span><span class="p">,</span><span class="w"> </span><span class="nx">attributes</span><span class="p">);</span>
<span class="w">    </span><span class="k">await</span><span class="w"> </span><span class="nx">ledger</span><span class="p">.</span><span class="nx">load</span><span class="p">(</span><span class="nx">services</span><span class="p">);</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">ledger</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This is pretty straightforward: we construct a new instance of <code>Ledger</code> (we'll
look at the <code>Ledger</code> implementation in a bit), call <code>load()</code>, and return the
object. This is an async function. No need to worry about the arguments as the
framework will handle these - we just plumb them through.</p>

<p><code>create()</code> is similar, except this is synchronous:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="nx">create</span><span class="p">(</span><span class="nx">document</span><span class="o">:</span><span class="w"> </span><span class="kt">IFluidDataStoreRuntime</span><span class="p">,</span><span class="w"> </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">ILedger</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">ledger</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Ledger</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nb">document</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">attributes</span><span class="p">);</span>
<span class="w">    </span><span class="nx">ledger</span><span class="p">.</span><span class="nx">initializeLocal</span><span class="p">();</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">ledger</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Instead of calling the async <code>ledger.load()</code>, we call <code>initializeLocal()</code>. We
again don't have to cover the arguments, but let's talk about the difference
between creating and loading.</p>

<p>In order to understand these, we need to introduce a new concept: the Fluid
container.</p>

<p>The container is a collection of distributed data structures defined by a
schema. This describes the data model of an application. In our case, to model
a game, we only need a ledger. For more complex applications, we might need
to use multiple distributed data structures. Fluid Framework uses containers
as the <q>unit</q> of data - we will never instantiate or use a distributed data
structure <em>standalone</em>. Even if we only need one, as in our case, we still need
to define a container.</p>

<p><img src="https://vladris.com/blog/2023/06/04/container.png" alt="Container diagram"/></p>

<p>The lifecycle shown in the diagram is:</p>

<ol>
<li>A client creates a container locally (this is where <code>create()</code> comes into
play). Based on the provided schema, the runtime will call <code>create()</code> for
all described data structures. At this point, we haven't yet connected to
the Fluid Relay. We are in what is called <em>detached</em> mode. Here we have the
opportunity to update our data structures before we connect and have other
clients see them.</li>
<li>We <em>attach</em> the container, meaning we connect to the Relay Service and start
a multi-user session. We can now expect changes to come in from other
clients.</li>
<li>Another client can now connect to the session. On this second client, since
the container was already created, the runtime will rely on the <code>load()</code>
functions to hydrate it.</li>
</ol>

<p>As a side note, the Fluid Relay can also store documents to persistent storage
so once the coauthoring session is over and all clients disconnect, the
document is persistent for future sessions.</p>

<p>For our Mental Poker application, we don't need to worry too much about
containers and schemas, we only need a minimal implementation consisting of a
container with a single distributed data structure: our <code>Ledger</code>. But it is
worth understanding how the runtime works.</p>

<p>We went over the full implementation of the <code>LedgerFactory</code>. You can also find
it in <a href="https://github.com/vladris/fluid-ledger/blob/main/packages/dds/src/ledgerFactory.ts">ledgerFactory.ts</a>.</p>

<h3>Implementation</h3>

<p>Let's now look at the actual implementation and learn about the anatomy of a
Fluid distributed data structure.</p>

<p>We need to import several types from the framework, which we'll cover as we
encounter them in the code below, or won't discuss if they are boilerplate.</p>
<div class="highlight"><pre><span/><span class="k">import</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">ISequencedDocumentMessage</span><span class="p">,</span>
<span class="w">    </span><span class="nx">MessageType</span>
<span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"@fluidframework/protocol-definitions"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">IChannelAttributes</span><span class="p">,</span>
<span class="w">    </span><span class="nx">IFluidDataStoreRuntime</span><span class="p">,</span>
<span class="w">    </span><span class="nx">IChannelStorageService</span><span class="p">,</span>
<span class="w">    </span><span class="nx">IChannelFactory</span><span class="p">,</span>
<span class="w">    </span><span class="nx">Serializable</span>
<span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"@fluidframework/datastore-definitions"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ISummaryTreeWithStats</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"@fluidframework/runtime-definitions"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">readAndParse</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"@fluidframework/driver-utils"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">createSingleBlobSummary</span><span class="p">,</span>
<span class="w">    </span><span class="nx">IFluidSerializer</span><span class="p">,</span>
<span class="w">    </span><span class="nx">SharedObject</span>
<span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"@fluidframework/shared-object-base"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">ILedger</span><span class="p">,</span><span class="w"> </span><span class="nx">ILedgerEvents</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"./interfaces"</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">LedgerFactory</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="kr">from</span><span class="w"> </span><span class="s2">"./ledgerFactory"</span><span class="p">;</span>
</pre></div>

<p>Note the last two imports: we import our interfaces and our <code>LedgerFactory</code>.</p>

<p>We'll define a couple of <em>delta operations</em>. That's the Fluid Framework name
for an operation (op) we send to the (or get back from) Fluid Relay service.</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">ILedgerOperation</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">IAppendOperation</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">IClearOperation</span><span class="p">;</span>

<span class="kd">interface</span><span class="w"> </span><span class="nx">IAppendOperation</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"append"</span><span class="p">;</span>
<span class="w">    </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">any</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">interface</span><span class="w"> </span><span class="nx">IClearOperation</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"clear"</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>In our case, we can have either an <code>IAppendOperation</code> or an <code>IClearOperation</code>.
The two together define the <code>ILedgerOperation</code> type.</p>

<p>The <code>IAppendOperation</code> includes a <code>value</code> property which can be anything. Both
<code>IAppendOperation</code> and <code>IClearOperation</code> have a <code>type</code> property, so we can see
at runtime which type we are dealing with.</p>

<p>We talked about how Fluid Framework is similar to git in the way it stores
documents as snapshots and ops. A lot of this is handled internally by the
framework, but our data structure needs to tell the service how we want to name
the snapshots, so we'll define a constant for this:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">snapshotFileName</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"header"</span><span class="p">;</span>
</pre></div>

<p>With this, we can start the implementation of <code>Ledger</code>.</p>
<div class="highlight"><pre><span/><span class="k">export</span><span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nx">Ledger</span><span class="o">&lt;</span><span class="nx">T</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">any</span><span class="o">&gt;</span>
<span class="w">    </span><span class="k">extends</span><span class="w"> </span><span class="nx">SharedObject</span><span class="o">&lt;</span><span class="nx">ILedgerEvents</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span>
<span class="w">    </span><span class="k">implements</span><span class="w"> </span><span class="nx">ILedger</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">}</span>
</pre></div>

<p>We derive from <code>SharedObject</code>, the base distributed data structure type. We
specify that this <code>SharedObject</code> will be firing <code>ILedgerEvents</code> and that it
implements the <code>ILedger</code> interface.</p>

<p>The framework expects a few functions used to construct objects. Our
constructor looks like this:</p>
<div class="highlight"><pre><span/><span class="kr">constructor</span><span class="p">(</span>
<span class="w">    </span><span class="nx">id</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span>
<span class="w">    </span><span class="nx">runtime</span><span class="o">:</span><span class="w"> </span><span class="kt">IFluidDataStoreRuntime</span><span class="p">,</span>
<span class="w">    </span><span class="nx">attributes</span><span class="o">:</span><span class="w"> </span><span class="kt">IChannelAttributes</span>
<span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">super</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">runtime</span><span class="p">,</span><span class="w"> </span><span class="nx">attributes</span><span class="p">,</span><span class="w"> </span><span class="s2">"fluid_ledger_"</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>The constructor takes an <code>id</code>, a <code>runtime</code>, and channel <code>attributes</code>. We don't
need to deeply understand these, as they are handled and passed in by the
framework. The last argument of the base class constructor is a telemetry
string prefix. We just need to provide a string unique to our data structure,
so we use <code>fluid_ledger_</code> in our case.</p>

<p>We also need a couple of static functions: <code>create()</code> and <code>getFactory()</code>:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="nx">create</span><span class="p">(</span><span class="nx">runtime</span><span class="o">:</span><span class="w"> </span><span class="kt">IFluidDataStoreRuntime</span><span class="p">,</span><span class="w"> </span><span class="nx">id?</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">runtime</span><span class="p">.</span><span class="nx">createChannel</span><span class="p">(</span><span class="nx">id</span><span class="p">,</span><span class="w"> </span><span class="nx">LedgerFactory</span><span class="p">.</span><span class="nx">Type</span><span class="p">)</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">Ledger</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="nx">getFactory</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">IChannelFactory</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">LedgerFactory</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>For <code>create()</code>, again we don't need to worry about <code>runtime</code> and <code>id</code>, as we
won't have to pass these in ourselves. We just need this function to forward
them to <code>runtime.createChannel()</code>. <code>createChannel()</code> also requires the unique
type, which we'll get from our <code>LedgerFactory</code>.</p>

<p>The <code>getFactory()</code> function simply creates a new instance of <code>LedgerFactory</code>.</p>

<p>We covered the constructor and factory functions. Next, let's look at the
internal data and the required <code>initializeLocalCore()</code> functions:</p>
<div class="highlight"><pre><span/><span class="k">private</span><span class="w"> </span><span class="nx">data</span><span class="o">:</span><span class="w"> </span><span class="kt">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="k">public</span><span class="w"> </span><span class="nx">get</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="p">[</span><span class="nb">Symbol</span><span class="p">.</span><span class="nx">iterator</span><span class="p">]();</span>
<span class="p">}</span>

<span class="k">protected</span><span class="w"> </span><span class="nx">initializeLocalCore</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="p">}</span>
</pre></div>

<p>This is very simple - we represent our ledger as an array of <code>Serializable&lt;T&gt;</code>.</p>

<p>The <code>get()</code> function, which we defined on our <code>IFluidLedger</code> interface, returns
the array's iterator.</p>

<p><code>initializeLocalCore()</code>, called internally by the runtime, simply sets <code>data</code>
to be an empty array.</p>

<p>We also need to implement saving and loading of the data structure. <q>Save</q> in
Fluid Framework world is called <em>summarize</em>: this is what the framework uses to
create snapshots.</p>
<div class="highlight"><pre><span/><span class="k">protected</span><span class="w"> </span><span class="nx">summarizeCore</span><span class="p">(</span>
<span class="w">    </span><span class="nx">serializer</span><span class="o">:</span><span class="w"> </span><span class="kt">IFluidSerializer</span>
<span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">ISummaryTreeWithStats</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">createSingleBlobSummary</span><span class="p">(</span>
<span class="w">        </span><span class="nx">snapshotFileName</span><span class="p">,</span>
<span class="w">        </span><span class="nx">serializer</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">handle</span><span class="p">)</span>
<span class="w">    </span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>We can use a framework-provided <code>createSingleBlobSummary</code>. In our case, we save
the whole <code>data</code> array and the <code>handle</code> (<code>handle</code> is an inherited attribute
representing a handle to the data structure, which the Framework uses for
nested data structure scenarios).</p>

<p>Here is how we load the data structure:</p>
<div class="highlight"><pre><span/><span class="k">protected</span><span class="w"> </span><span class="k">async</span><span class="w"> </span><span class="nx">loadCore</span><span class="p">(</span><span class="nx">storage</span><span class="o">:</span><span class="w"> </span><span class="kt">IChannelStorageService</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="ow">void</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">content</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">await</span><span class="w"> </span><span class="nx">readAndParse</span><span class="o">&lt;</span><span class="nx">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">[]</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">storage</span><span class="p">,</span>
<span class="w">        </span><span class="nx">snapshotFileName</span>
<span class="w">    </span><span class="p">);</span>
<span class="w">    </span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">serializer</span><span class="p">.</span><span class="nx">decode</span><span class="p">(</span><span class="nx">content</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>For both summarize and load, we rely on Framework-provided utilities.</p>

<p>We can now focus on the non-boilerplate bits: implementing our <code>append()</code>
and <code>clear()</code>. Let's start with <code>append()</code>:</p>
<div class="highlight"><pre><span/><span class="k">private</span><span class="w"> </span><span class="nx">applyInnerOp</span><span class="p">(</span><span class="nx">content</span><span class="o">:</span><span class="w"> </span><span class="kt">ILedgerOperation</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="nx">content</span><span class="p">.</span><span class="kr">type</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="s2">"append"</span><span class="o">:</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="s2">"clear"</span><span class="o">:</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">submitLocalMessage</span><span class="p">(</span><span class="nx">content</span><span class="p">);</span>
<span class="w">            </span><span class="k">break</span><span class="p">;</span>

<span class="w">        </span><span class="nx">default</span><span class="o">:</span>
<span class="w">            </span><span class="kt">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Unknown operation"</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="k">private</span><span class="w"> </span><span class="nx">appendCore</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">    </span><span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s2">"append"</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">public</span><span class="w"> </span><span class="nx">append</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">Serializable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">opValue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">serializer</span><span class="p">.</span><span class="nx">encode</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">handle</span><span class="p">);</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">isAttached</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">op</span><span class="o">:</span><span class="w"> </span><span class="kt">IAppendOperation</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"append"</span><span class="p">,</span>
<span class="w">            </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">opValue</span>
<span class="w">        </span><span class="p">};</span>

<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">applyInnerOp</span><span class="p">(</span><span class="nx">op</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">appendCore</span><span class="p">(</span><span class="nx">opValue</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>applyInnerOp()</code> is common to both <code>append()</code> and <code>clear()</code>. This is the
function that takes an <code>ILedgerOperation</code> and sends it to the Fluid Relay
service. <code>submitLocalMessage()</code> is inherited from the base <code>SharedObject</code>.</p>

<p><code>appendCore()</code> effectively updates <code>data</code> and fires the <code>append</code> event.</p>

<p><code>append()</code> first serializes the provided value using the inherited
Framework-provided <code>serializer</code>. We assign this to <code>opValue</code>. We then need
to cover both the attached and detached scenarios. If attached, it means
we are connected to a Fluid Relay and we are in the middle of a coauthoring
session. In this case, we create an <code>IAppendOperation</code> object and call
<code>applyInnerOp()</code>. If we are detached, it means we created our data structure
(and its container) on this client, but we are not connected to a service
yet. In this case we call <code>appendCore()</code> to immediately append the value
since there is no service to send the op to and get it back sequenced.</p>

<p><code>clear()</code> is very similar:</p>
<div class="highlight"><pre><span/><span class="k">private</span><span class="w"> </span><span class="nx">clearCore</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">slice</span><span class="p">();</span>

<span class="w">    </span><span class="k">this</span><span class="p">.</span><span class="nx">data</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="k">this</span><span class="p">.</span><span class="nx">emit</span><span class="p">(</span><span class="s2">"clear"</span><span class="p">,</span><span class="w"> </span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">public</span><span class="w"> </span><span class="nx">clear</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">isAttached</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">op</span><span class="o">:</span><span class="w"> </span><span class="kt">IClearOperation</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="kr">type</span><span class="o">:</span><span class="w"> </span><span class="s2">"clear"</span>
<span class="w">        </span><span class="p">};</span>

<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">applyInnerOp</span><span class="p">(</span><span class="nx">op</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">clearCore</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>clearCore()</code> effectively clears <code>data</code> and emits the <code>clear</code> event.</p>

<p><code>clear()</code> handles both the attached and detached scenarios.</p>

<p>So far we update our data immediately when detached, and when attached we
send the op to the Relay Service. The missing piece is handling ops as
they come back from the Relay Service. We do this in <code>processCore()</code>,
another function the runtime expects us to provide:</p>
<div class="highlight"><pre><span/><span class="k">protected</span><span class="w"> </span><span class="nx">processCore</span><span class="p">(</span><span class="nx">message</span><span class="o">:</span><span class="w"> </span><span class="kt">ISequencedDocumentMessage</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="kr">type</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">MessageType</span><span class="p">.</span><span class="nx">Operation</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">const</span><span class="w"> </span><span class="nx">op</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">message</span><span class="p">.</span><span class="nx">contents</span><span class="w"> </span><span class="kr">as</span><span class="w"> </span><span class="nx">ILedgerOperation</span><span class="p">;</span>

<span class="w">        </span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="nx">op</span><span class="p">.</span><span class="kr">type</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">case</span><span class="w"> </span><span class="s2">"append"</span><span class="o">:</span>
<span class="w">                </span><span class="k">this</span><span class="p">.</span><span class="nx">appendCore</span><span class="p">(</span><span class="nx">op</span><span class="p">.</span><span class="nx">value</span><span class="p">);</span>
<span class="w">                </span><span class="k">break</span><span class="p">;</span>
<span class="w">            </span><span class="k">case</span><span class="w"> </span><span class="s2">"clear"</span><span class="o">:</span>
<span class="w">                </span><span class="k">this</span><span class="p">.</span><span class="nx">clearCore</span><span class="p">();</span>
<span class="w">                </span><span class="k">break</span><span class="p">;</span>
<span class="w">            </span><span class="nx">default</span><span class="o">:</span>
<span class="w">                </span><span class="kt">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Unknown operation"</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This function is called by the runtime when the Fluid Relay sends the client
a message. In our case, we only care about messages that are operations. We
only support <code>append</code> and <code>clear</code> operations. We handle these by calling the
<code>appendCore()</code> and <code>clearCore()</code> we just saw - since these ops are coming
from the service, we can safely append them to our <code>data</code> (we have the
guarantee that all clients will get these in the same order).</p>

<p>And we're almost done. We need to implement <code>onDisconnect()</code>, which is called
when we disconnect from the Fluid Relay. This gives the distributed data
structure a chance to run some code but in our case we don't need to do
anything.</p>
<div class="highlight"><pre><span/><span class="k">protected</span><span class="w"> </span><span class="nx">onDisconnect</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span>
</pre></div>

<p>Finally, we also need <code>applyStashedOp()</code>. This is used in offline mode. For
some applications, we might want to provide some functionality when offline -
a client can keep making updates, which get <em>stashed</em>. We won't dig into this
since for Mental Poker we can't have a single client play offline - we simply
throw an exception if this function ever gets called:</p>
<div class="highlight"><pre><span/><span class="k">protected</span><span class="w"> </span><span class="nx">applyStashedOp</span><span class="p">(</span><span class="nx">content</span><span class="o">:</span><span class="w"> </span><span class="kt">unknown</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">throw</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Not supported"</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>The full implementation is in <a href="https://github.com/vladris/fluid-ledger/blob/main/packages/dds/src/ledger.ts">ledger.ts</a>.</p>

<p>And that's it! We have a fully functioning distributed data structure we can
use to model games.</p>

<h2>Demo</h2>

<p>The GitHub repo also includes a <a href="https://github.com/vladris/fluid-ledger/tree/main/packages/demo-app">demo app</a>:
a collaborative coloring application where multiple clients can simultaneously
color a drawing.</p>

<p>In this case, we model coloring operations as <code>x</code> and <code>y</code> coordinates, and a
<code>color</code>. As users click on the drawing, we append these operations to the
ledger and play them back to color the drawing using flood fill.</p>
]]></description>
      <pubDate>Sun, 04 Jun 2023 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/04/12/notes-on-documentation.html</link>
      <guid>https://vladris.com/blog/2023/04/12/notes-on-documentation.html</guid>
      <title><![CDATA[Notes on Documentation]]></title>
      <description><![CDATA[<h1>Notes on Documentation</h1>

<p>I spent a bunch of time lately revamping some documentation and this got me
thinking. In terms of tooling, even state-of-the-art documentation pipelines
are missing some key features. This is also an area where we can directly apply
LLMs. In this post, I'll jot down some thoughts of how things could look like
in a more perfect world. Of course, here I'm referring to documentation
associated with software projects.</p>

<h2>Build from source</h2>

<p>This first one isn't unheard of: documentation should be captured in source
control and generated from there as a static website. There are two major types
of documentation: API reference and <em>articles</em> that aren't tied to a specific
API.</p>

<p>API reference should be extracted from code comments. Different languages have
different levels of <q>official</q> support for this. C# has out-of-the-box XML
documentation (<code>///</code>), JavaScript has the non-standard but popular <a href="https://jsdoc.app/">JsDoc</a>
etc.</p>

<p>Articles on the other hand should be written as stand-alone Markdown files.</p>

<p>A good documentation pipeline should support both. My team is using <a href="https://dotnet.github.io/docfx/">DocFX</a>
to that effect, though TypeScript is not supported out-of-the-box and requires
some additional packages to set up.</p>

<h2>CI validation</h2>

<p>Commenting APIs should be enforced via linter. We have tools like <a href="https://github.com/StyleCop/StyleCop">StyleCop</a>
for C# and a <a href="https://www.npmjs.com/package/eslint-plugin-jsdoc">JsDoc plugin for eslint</a>
for JavaScript. At the very least, all of the public API surface should be
documented. If you introduce a new public API without corresponding
documentation, this should cause a build break.</p>

<p>For technical documentation, many times articles also contain code samples.
These run the risk of getting out of sync with the actual code as the code
churns. In an ideal world, we should be able to associate a code snippet from
an article with a test that runs with the CI pipeline. Documentation might
skip scaffolding for clarity, so it's likely harder to simply attempt running
the exact code snippet. But we should have a way to pull the snipped into a
test that provides that scaffolding.</p>

<p>Alternately, enforce that running all snippets in an article in order works -
treat articles more like Jupyter notebooks, where the runtime maintains some
context, so if, for example, I import something in the first code snippet, the
import is available to subsequent code snippets.</p>

<p>The key thing is to have some way to validate at build time that all code
examples actually work and not allow breaking changes, even if the only thing
that breaks is documentation.</p>

<h2>Ownership</h2>

<p>From my personal experience, documentation is usually treated as an
afterthought. From time to time there is a big push to update things, but it's
rare that everyone is constantly working towards improving docs.</p>

<p>Unless documentation reaches a critical mass of contributors to ensure
everything is kept in order, it's best to have clear ownership of each article.
Git history is not always the best for finding owners - sometimes the last
author is no longer with the team or with the company, or maybe last commits
just moved the file around or fixed typos.</p>

<p>This concern goes beyond documentation, in general I'd love to see an ownership
tracking system that can associate assets with people and is also org-chart
aware - so if an owner changes teams, this gets flagged and a new owner must be
provided.</p>

<h2>Inline fragments</h2>

<p>While working on documentation, I noticed that for a large enough project, some
information tends to repeat across multiple articles. Maybe as part of a summary
on the front page, then again in an article covering some of the details, and
once more incidentally in a related article.</p>

<p>The problem is that if something changes and I only update one of the articles
(maybe I'm not aware of all the places this shows up), documentation can start
contradicting itself. This is something that is not part of the common Markdown
syntax but I'd love to have a way to inline a paragraph across multiple
documents to avoid this.</p>

<h2>Style guides</h2>

<p>All documentation should include a style guide. Some guidelines encourage
writing for easier reading, so apply in most cases. For example:</p>

<ul>
<li>Avoid passive voice.</li>
<li>Encourage diagrams and pictures vs. very long descriptions.</li>
</ul>

<p>Some guidelines depend on the type of article. If you're documenting a design
decision, explain the reasoning and list other options considered and why these
weren't adopted. On the other hand, if you are writing a troubleshooting guide,
no need to explain the <em>why</em>, just what steps the reader needs to take.</p>

<p>Unfortunately I haven't seen a lot of such guides accompany projects. I wish
we had a set of industry standard ones to simply plug in, like we do with open
source licenses.</p>

<h2>Information architecture</h2>

<p>In many cases, there is little effort put into structuring the documentation.
We start with <code>/docs</code> then as articles pile up, we create new subfolders
organically.</p>

<p>Much like we want some high-level design of a system, we should also require
a high-level design of the documentation. What are the key topics and
sub-sections? This doesn't even need to be reinvented for each new project,
I expect there's a handful of structures which can support most projects,
so much like style guides, it would be great to have these available
of-the-shelf.</p>

<h3>An alternative to hierarchy</h3>

<p>I started this post talking about building documentation from source, which
naturally maps to articles being files organized in folders (categories). This
type of organization - categories and subcategories - works well up to a
certain volume of information.</p>

<p>At some point, it gets hard to figure out which subcategory something fits in:
it might fit just as well in multiple places. Here the folder categorization
breaks down: there is no clear hierarchy of nested folders in which to fit
everything.</p>

<p>At alternative to hierarchies are tags. Maintain a curated set of tags, then
tag each article with one or more tags. You can then browse by tag, but have
articles show up under multiple tags. This tends to work better with larger
volumes of information, but it's harder to map to a file and folder structure.</p>

<h2>AI</h2>

<p>With the popularity of large language models, I see many applications
throughout the lifecycle:</p>

<h3>Authoring</h3>

<p>Generative AI can help coauthor documentation. GitHub Copilot <a href="https://learn.microsoft.com/en-us/shows/introduction-to-github-copilot/how-to-write-documentation-with-copilot-suggestions-5-of-6">already does
this</a>.
As models get better and cheaper to run, I expect they will be more and more
involved in writing documentation.</p>

<h3>Reviewing and editing</h3>

<p>Given a style guide, a model can review how closely a document adheres to it
and suggest changes to match the guide.</p>

<p>With a knowledge of the whole documentation, a model could also spot
contradictions (the problem I mentioned in the <strong>Inline fragments</strong> section).
This could be a step in the CI pipeline to ensure consistency.</p>

<p>A model could potentially also act as a reader and provide feedback on how
clear the documentation is.</p>

<h3>Retrieval</h3>

<p>Most tools generating documentation from source provide very rudimentary search
capabilities. OpenAI offers text and code <a href="https://openai.com/blog/introducing-text-and-code-embeddings">embedding APIs</a>
which enable semantic search and natural language querying. Using something
like this on documentation should make finding things much easier.</p>

<h3>Q&amp;A</h3>

<p>Models can also be used to answer questions, so instead of readers having to
search the docs for what they need, they can simply ask questions. A model
can provide answers based on the documentation (and the codebase). This takes
retrieval a step further: users can simply get their questions answered by a
model. In some cases articles might not even be needed, as the model can
explain in real time how the code is supposed to be used.</p>

<h2>Summary</h2>

<p>I believe as of today, even the best tools available for documentation leave
room for improvement and large language models have the potential to radically
change the game.</p>

<p>In this post we looked at:</p>

<ul>
<li>The two main types of documentation: API reference and articles, which should
both live in source control.</li>
<li>API reference should be extracted from code comments.</li>
<li>Articles should be written as Markdown.</li>
<li>CI validation for documentation: enforce API documentation and ensure code
samples still work.</li>
<li>Ownership tracking: ensuring someone feels responsible for every piece of
documentation.</li>
<li>Inline fragments as a proposed solution to keep information in sync across
multiple documents.</li>
<li>Style guides for documentation to ensure consistent &amp; readable articles.</li>
<li>Information architecture to improve overall structure and navigation.</li>
<li>Potential AI applications throughout the lifecycle:

<ul>
<li>Coauthoring documentation with generative AI.</li>
<li>Reviewing documentation and providing suggestions (for style, consistency,
readability).</li>
<li>Finding the right documentation using embeddings.</li>
<li>Answering natural language questions.</li>
</ul></li>
</ul>

<p>Some of these features exist and some of these practices are adopted in some
projects, but most are not widely implemented. I'm curious to see how the
landscape will look like in a few years and how AIs will change the way we
learn and get our questions answered.</p>
]]></description>
      <pubDate>Wed, 12 Apr 2023 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html</link>
      <guid>https://vladris.com/blog/2023/03/14/mental-poker-part-1-cryptography.html</guid>
      <title><![CDATA[Mental Poker Part 1: Cryptography]]></title>
      <description><![CDATA[<h1>Mental Poker Part 1: Cryptography</h1>

<p>In the <a href="https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html">previous post</a>
I outlined some of the interesting bits of putting together a <a href="https://en.wikipedia.org/wiki/Mental_poker">Mental Poker</a>
toolkit. In this post I will talk about cryptography.</p>

<p>The golden rule when it comes to cryptography code is to not roll your own,
rather use something that's been battle-tested. That said, I could not find
what I needed so had to implement some stuff. I urge you not to rely on my
implementation for high-stakes poker, as it is likely buggy.</p>

<p>With the disclaimer out of the way, let's look at what we need to support
Mental Poker.</p>

<h2>Card shuffling</h2>

<p>Recap from <a href="https://vladris.com/blog/2021/12/11/mental-poker.html">this old post</a>
when I first got interested in the subject:</p>

<blockquote>
<p>Mental poker requires a commutative encryption function. If we encrypt
  \(A\) using \(Key_1\) then encrypting the result using \(Key_2\), we should be
  able to decrypt the result back to \(A\) regardless of the order of
  decryption (first with \(Key_1\) and then with \(Key_2\), or vice-versa).</p>

<p>Here is how Alice and Bob play a game of mental poker:</p>

<ul>
<li>Alice takes a deck of cards (an array), shuffles the deck, generates
a secret key \(K_A\), and encrypts each card with \(K_A\).</li>
<li>Alice hands the shuffled and encrypted deck to Bob. At this point,
Bob doesn't know what order the cards are in (since Alice encrypted
the cards in the shuffled deck).</li>
<li>Bob takes the deck, shuffles it, generates a secret key \(K_B\), and
encrypts each card with \(K_B\).</li>
<li>Bob hands the deck to Alice. At this point, neither Alice nor Bob
know what order the cards are in. Alice got the deck back reshuffled
and re-encrypted by Bob, so she no longer knows where each card
ended up. Bob reshuffled an encrypted deck, so he also doesn't know
where each card is.</li>
</ul>

<p>At this point the cards are shuffled. In order to play, Alice and Bob
  also need the capability to look at individual cards. In order to enable
  this, the following steps must happen:</p>

<ul>
<li>Alice decrypts the shuffled deck with her secret key \(K_A\). At this
point she still doesn't know where each card is, as cards are still
encrypted with \(K_B\).</li>
<li>Alice generates a new set of secret keys, one for each card in the
deck. Assuming a 52-card deck, she generates
\(K_{A_1} ... K_{A_{52}}\) and encrypts each card in the deck with one
of the keys.</li>
<li>Alice hands the deck of cards to Bob. At this point, each card is
encrypted by Bob's key, \(B_K\), and one of Alice's keys, \(K_{A_i}\).</li>
<li>Bob decrypts the cards using his key \(K_B\). He still doesn't know
where each card is, as now the cards are encrypted with Alice's
keys.</li>
<li>Bob generates another set of secret keys, \(K_{B_1} ... K_{B_{52}}\),
and encrypts each card in the deck.</li>
<li>Now each card in the deck is encrypted with a unique key that only
Alice knows and a unique key only Bob knows.</li>
</ul>

<p>If Alice wants to look at a card, she asks Bob for his key for that
  card. For example, if Alice draws the first card, encrypted with
  \(K_{A_1}\) and \(K_{B_1}\), she asks Bob for \(K_{B_1}\). If Bob sends her
  \(K_{B_1}\), she now has both keys to decrypt the card and <q>look</q> at it.
  Bob still can't decrypt it because he doesn't have \(K_{A_1}\).</p>

<p>This way, as long as both Alice and Bob agree that one of them is
  supposed to <q>see</q> a card, they exchange keys as needed to enable this.</p>
</blockquote>

<p>The reason I ended up hand-rolling some cryptography is that off-the-shelf
encryption algorithms are non-commutative. With a non-commutative algorithm,
the above steps don't work: Alice cannot decrypt the deck with her secret
key \(K_A\) after Bob shuffled it and encrypted it with \(K_B\).</p>

<p>The analogy I used in <a href="https://www.youtube.com/watch?v=F1gPTXAllxY">this tech talk</a>
is boxes and locks: if we have commutative encryption, we put the secret
information in a box and both Alice (using \(K_A\)) and Bob (using \(K_B\)) put
a lock on that box. It doesn't really matter in which order we unlock the two
locks - as long as both are unlocked, we can get to the content. On the other
hand, if we have non-commutative encryption, this is equivalent of Alice
putting the secret in a box locked with \(K_A\), and Bob putting the whole locked
box in another box locked with \(K_B\). Now Alice's key is useless while the
outerbox only has the \(K_B\) lock on it.</p>

<p>There aren't as many applications for commutative encryption, so the popular
libraries out there provide only non-commutative encryption algorithms. The
commutative encryption algorithm we will look at is SRA.</p>

<h2>SRA</h2>

<p>The SRA encryption algorithm was designed by Shamir, Rivest, and Adleman of
RSA fame. Both algorithms use their initials, but the industry-standard RSA is
non-commutative. SRA, on the other hand, is.</p>

<p>SRA works like this: we need a large prime number \(P\). This seed prime is
shared by all players. To generate encryption keys from it, let \(\phi = P - 1\).
Each player needs to find another prime \(E\), such that \(\phi\) and \(E\) are
coprime. \(E\) is that player's encryption key. The decryption key is derived
from \(\phi\) and \(E\) as the modulo-inverse \(D\) such that
\(E * D \equiv 1 \pmod{\phi}\).</p>

<p>To encrypt a number \(N\), we raise it to \(E\) modulo \(P\). To decrypt an encrypted
number \(N'\), we raise it to \(D\) modulo \(P\).</p>

<p>Then if player 1 encrypts a payload with \(E_1\) and player 2 encrypts again
using \(E_2\), the message can be decrypted by applying \(D_1\) and \(D_2\) in any
order. Remember, this is key to the card shuffling algorithm.</p>

<p>For a simple implementation, we can use arbitrarily large integers (<a href="https://developer.mozilla.org/en-US/docs/web/javascript/reference/global_objects/bigint">BigInt</a>).
Unfortunately, the built-in JavaScript math libraries only work with <code>number</code>
values, so we need to implement a bit of math.</p>

<h2>BigInt math</h2>

<p>First, we need to find the greatest common divisor of two numbers:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">gcd</span><span class="p">(</span><span class="nx">a</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">bigint</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">[</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">b</span><span class="p">,</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">b</span><span class="p">];</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">a</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>We use this to check if two numbers are coprime (their GCD is 1).</p>

<p>Next, we need modulo inverse (find <code>x</code> such that <code>(a * x) % m == 1</code>). One way
of doing this is using Euclidean Division. We use the same algorithm we used
for GCD, but we keep track of the values we find at each step. Finally, if <code>a</code>
is <code>1</code>, it means there is no modulo inverse. Otherwise we find the modulo
inverse by starting with a pair of numbers <code>x = 1, y = 0</code> and iterating over
the values we found at the previous step, updating <code>x</code> to be <code>y</code> and <code>y</code> to be
<code>x - y * (a / b)</code> where <code>a</code> and <code>b</code> are values we saved from the previous step:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">modInverse</span><span class="p">(</span><span class="nx">a</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">m</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">((</span><span class="nx">a</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">m</span><span class="p">;</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">a</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"Invalid input"</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// Find GCD (and remember numbers at each step)</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">m</span><span class="p">;</span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">[</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">b</span><span class="p">,</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">b</span><span class="p">];</span>
<span class="w">        </span><span class="nx">s</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span><span class="w"> </span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">b</span><span class="w"> </span><span class="p">});</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">a</span><span class="w"> </span><span class="o">!==</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="s2">"No inverse"</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// Find the inverse</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">);</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">);</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">s</span><span class="p">.</span><span class="nx">length</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mf">2</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="o">--</span><span class="nx">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">[</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nx">y</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="nx">s</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">a</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nx">s</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">b</span><span class="p">)];</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">((</span><span class="nx">y</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">m</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">m</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This gives us the modulo inverse. To recap, we use this once we have a large
prime \(P\) with \(\phi = P - 1\) and a large prime \(E\) such that
\(gcd(E, \phi) = 1\) to find our decryption key \(D\).</p>

<p>We also need modulo exponentiation for encryption/decryption. Since we are
dealing with large numbers, we will implement exponentiation using the <a href="https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication">ancient
Egyptian multiplication algorithm</a>.
To raise <code>b</code> to <code>e</code> modulo <code>m</code>, if <code>e</code> is <code>1</code>, we return <code>b</code>. Otherwise we
recursively raise <code>(b * b) % m</code> to <code>e / 2</code> modulo <code>m</code>. Whenever <code>e</code> is odd,
we multiply the recursion result by an additional <code>b</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">exp</span><span class="p">(</span><span class="nx">b</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">m</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">bigint</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">b</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">exp</span><span class="p">((</span><span class="nx">b</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nx">b</span><span class="p">)</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">m</span><span class="p">,</span><span class="w"> </span><span class="nx">e</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="nx">m</span><span class="p">);</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">e</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">result</span><span class="w"> </span><span class="o">*=</span><span class="w"> </span><span class="nx">b</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">m</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This algorithm runs in log <code>e</code> time and keeps the large numbers to a manageable
size since we apply modulo <code>m</code> at each step. We have most of the math pieces in
place. The only thing missing is a way to generate large primes.</p>

<h2>Generating large primes</h2>

<p>One way of generating large primes is through trial and error: we generate a
large number, check if it is prime, and repeat if it isn't. We can generate a
large number by filling a byte array with random values, then converting it
into a <code>BigInt</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">randBigInt</span><span class="p">(</span><span class="nx">sizeInBytes</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">128</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">bigint</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">buffer</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nb">Uint8Array</span><span class="p">(</span><span class="nx">sizeInBytes</span><span class="p">);</span>
<span class="w">    </span><span class="nx">crypto</span><span class="p">.</span><span class="nx">getRandomValues</span><span class="p">(</span><span class="nx">buffer</span><span class="p">);</span>

<span class="w">    </span><span class="c1">// Build a bigint out of the buffer</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">);</span>
<span class="w">    </span><span class="nx">buffer</span><span class="p">.</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">n</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">256</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="nx">n</span><span class="p">);</span>
<span class="w">    </span><span class="p">});</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This gives us a random number of as many bytes as we want (default being 128
bytes, i.e. 1024 bits). Since we are dealing with very large numbers, we can't
naively test for primality of \(N\) by trying divisions up to \(\sqrt{N}\), this is
too expensive. We instead use the probabilistic <a href="https://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test">Miller-Rabin test</a>.</p>

<p>In short, Miller-Rabin works like this: we can write an integer \(N\) (our prime
candidate) as \(N = 2^S * D + 1\) where \(S\) and \(D\) are positive integers.</p>

<p>Let's take another integer \(A\) coprime with \(N\). \(N\) is likely to be prime if
\(A^D \equiv 1 \pmod{N}\) or \(A^{2^{R}*D} \equiv -1 \pmod{N}\) for some
\(0 &lt;= R &lt;= S\). If this is not the case, then \(N\) is not a prime and \(A\) is
called a <em>witness</em> of the compositeness of \(N\).</p>

<p>This is a probabilistic test, so we can tell whether \(N\) is for sure non-prime
or likely to be prime. Unfortunately, we can't tell for sure that \(N\) is prime.
We need to run multiple iterations of this picking different \(A\) values until
we are satisfied that \(N\) is <em>likely enough</em> to be prime.</p>

<p>First, we need a helper function that checks \(A\) is not a <em>witness</em> of \(N\),
given \(A\), \(N\), and \(S\) and \(D\) such that \(N = S^2 * D + 1\).</p>

<p>We compute \(U\) as \(A^D \pmod{N}\). If \(U - 1 = 0\) or \(U + 1 = N\), then \(A\) is
not a witness of \(N\). Otherwise, we repeat \(S - 1\) times: \(U = U^2 \pmod{N}\)
and \(A\) is not a witness if \(U + 1 = N\). At this point, if we haven't confirmed
that \(A\) is not a witness, we consider \(A\) a witness of \(N\) thus \(N\) is not
prime. These are simply the checks described above (\(A^D \equiv 1 \pmod{N}\)
and \(A^{2^{R}*D} \equiv -1 \pmod{N}\)) in implementation form.</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">isNotWitness</span><span class="p">(</span><span class="nx">a</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">d</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">s</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">a</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// u is a ^ d % n</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">exp</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">d</span><span class="p">,</span><span class="w"> </span><span class="nx">n</span><span class="p">);</span>

<span class="w">    </span><span class="c1">// a is not a witness if u - 1 = 0 or u + 1 = n</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">u</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">u</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// Repeat s - 1 times</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">);</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">);</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// u = u ^ 2 % n</span>
<span class="w">        </span><span class="nx">u</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">exp</span><span class="p">(</span><span class="nx">u</span><span class="p">,</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">2</span><span class="p">),</span><span class="w"> </span><span class="nx">n</span><span class="p">);</span>

<span class="w">        </span><span class="c1">// a is not a witness if u = n - 1</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">u</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nx">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// a is a witness of n</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>With this, we can finally implement Miller-Rabin. We first check a few trivial
cases (<code>2</code> and <code>3</code> are prime, even numbers are non-prime). We then find \(S\) and
\(D\) such that our number \(N = 2^S * D + 1\) (we do this by factoring out powers
of 2 from \(N - 1\)).</p>

<p>We then repeat the test: get a random number \(A &lt; N\). If \(A\) is a witness of
\(N\), then \(N\) is not prime. If we run this test enough times, we can safely
assume the number is prime. According to <a href="https://stackoverflow.com/questions/6325576/how-many-iterations-of-rabin-miller-should-i-use-for-cryptographic-safe-primes">this</a>,
40 rounds should be good enough for a 1024 bit prime.</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">millerRabinTest</span><span class="p">(</span><span class="nx">candidate</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="p">{</span>
<span class="w">  </span><span class="c1">// Handle some obvious cases</span>
<span class="w">  </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">candidate</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">candidate</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">3</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">  </span><span class="p">}</span>
<span class="w">  </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">candidate</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="nx">candidate</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">2</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="c1">// Find s and d</span>
<span class="w">  </span><span class="kd">let</span><span class="w"> </span><span class="nx">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">candidate</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">);</span>
<span class="w">  </span><span class="kd">let</span><span class="w"> </span><span class="nx">s</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">);</span>

<span class="w">  </span><span class="k">while</span><span class="w"> </span><span class="p">((</span><span class="nx">d</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">))</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="nx">d</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">d</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">);</span>
<span class="w">      </span><span class="nx">s</span><span class="o">++</span><span class="p">;</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="c1">// Test 40 rounds.</span>
<span class="w">  </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0</span><span class="p">;</span><span class="w"> </span><span class="nx">k</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mf">40</span><span class="p">;</span><span class="w"> </span><span class="nx">k</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="kd">let</span><span class="w"> </span><span class="nx">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">randBigInt</span><span class="p">()</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">candidate</span><span class="p">;</span>

<span class="w">      </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">isNotWitness</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="w"> </span><span class="nx">d</span><span class="p">,</span><span class="w"> </span><span class="nx">s</span><span class="p">,</span><span class="w"> </span><span class="nx">candidate</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">          </span><span class="k">return</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>
<span class="w">      </span><span class="p">}</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="k">return</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Note <code>d</code> and <code>s</code> above are technically only needed in <code>isNotWitness()</code>, but
since they are based on our prime candidate, we compute them once and pass them
as arguments to <code>isNotWitness()</code> rather than having to recompute them on each
call of the function.</p>

<p>We can finally implement our prime generator. We simply generate large numbers
and repeat until Miller-Rabin confirms we got a prime number:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">randPrime</span><span class="p">(</span><span class="nx">sizeInBytes</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">128</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">bigint</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">candidate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">);</span>

<span class="w">    </span><span class="k">do</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">candidate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">randBigInt</span><span class="p">(</span><span class="nx">sizeInBytes</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">millerRabinTest</span><span class="p">(</span><span class="nx">candidate</span><span class="p">));</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">candidate</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<h2>Cryptography</h2>

<p>With the low-level math out of the way, we can implement the cryptography API.
First, we will define an <code>SRAKeyPair</code> as consisting of the initial large prime
\(P\) and the derived \(E\) and \(D\) used for encryption/decryption:</p>
<div class="highlight"><pre><span/><span class="kr">type</span><span class="w"> </span><span class="nx">SRAKeyPair</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">prime</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">;</span>
<span class="w">    </span><span class="nx">enc</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">;</span>
<span class="w">    </span><span class="nx">dec</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>We can generate a large prime using <code>randPrime()</code>. From such a prime, we can
generate an <code>SRAKeyPair</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">generateKeyPair</span><span class="p">(</span><span class="nx">largePrime</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">size</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">128</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">SRAKeyPair</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">const</span><span class="w"> </span><span class="nx">phi</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">largePrime</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">);</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">enc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">);</span>

<span class="w">    </span><span class="c1">// Trial and error</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Generate a large prime</span>
<span class="w">        </span><span class="nx">enc</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">randPrime</span><span class="p">(</span><span class="nx">size</span><span class="p">);</span>

<span class="w">        </span><span class="c1">// Stop when generated prime and passed in prime - 1 are coprime</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">gcd</span><span class="p">(</span><span class="nx">enc</span><span class="p">,</span><span class="w"> </span><span class="nx">phi</span><span class="p">)</span><span class="w"> </span><span class="o">===</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">1</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// enc is our encryption key, now let's find dec as the mod inverse of enc</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">dec</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">modInverse</span><span class="p">(</span><span class="nx">enc</span><span class="p">,</span><span class="w"> </span><span class="nx">phi</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">prime</span><span class="o">:</span><span class="w"> </span><span class="kt">largePrime</span><span class="p">,</span>
<span class="w">        </span><span class="nx">enc</span><span class="o">:</span><span class="w"> </span><span class="kt">enc</span><span class="p">,</span>
<span class="w">        </span><span class="nx">dec</span><span class="o">:</span><span class="w"> </span><span class="kt">dec</span><span class="p">,</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>If we have an <code>SRAKeyPair</code>, we can encrypt/decrypt numbers using the modulo
exponentiation function we defined above (<code>exp()</code>):</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">encryptInt</span><span class="p">(</span><span class="nx">n</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">exp</span><span class="p">(</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="p">.</span><span class="nx">enc</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="p">.</span><span class="nx">prime</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">decryptInt</span><span class="p">(</span><span class="nx">n</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">exp</span><span class="p">(</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="p">.</span><span class="nx">dec</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="p">.</span><span class="nx">prime</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>We can also convert a string into a BigInt and vice-versa. Assuming we only
have character codes below 256 (so ASCII), we can simply encode the string
as a 256-base number where each digit is a character:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">stringToBigInt</span><span class="p">(</span><span class="nx">str</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">bigint</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">);</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">c</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">str</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mf">255</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">throw</span><span class="w"> </span><span class="ne">Error</span><span class="p">(</span><span class="sb">`Unexpected char code </span><span class="si">${</span><span class="nx">c</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mf">0</span><span class="p">)</span><span class="si">}</span><span class="sb"> for </span><span class="si">${</span><span class="nx">c</span><span class="si">}</span><span class="sb">`</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">256</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="nx">c</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mf">0</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The ASCII assumption is reasonable, since we use this at a protocol level, not
as part of the user experience. We can decode such a number back into a string
using division and modulo:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">bigIntToString</span><span class="p">(</span><span class="nx">n</span><span class="o">:</span><span class="w"> </span><span class="kt">bigint</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">""</span><span class="p">;</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">m</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">0</span><span class="p">);</span>

<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">[</span><span class="nx">n</span><span class="p">,</span><span class="w"> </span><span class="nx">m</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="nx">n</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">256</span><span class="p">),</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nb">BigInt</span><span class="p">(</span><span class="mf">256</span><span class="p">)];</span>
<span class="w">        </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span><span class="p">.</span><span class="nx">fromCharCode</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="nx">m</span><span class="p">))</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Now that we have these conversions, we can can implement string
encryption/decryption on top of our <code>encryptInt()</code> and <code>decryptInt()</code>
functions:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">encryptString</span><span class="p">(</span><span class="nx">clearText</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">bigIntToString</span><span class="p">(</span><span class="nx">encryptInt</span><span class="p">(</span><span class="nx">stringToBigInt</span><span class="p">(</span><span class="nx">clearText</span><span class="p">),</span><span class="w"> </span><span class="nx">kp</span><span class="p">));</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">decryptString</span><span class="p">(</span><span class="nx">cypherText</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">bigIntToString</span><span class="p">(</span><span class="nx">decryptInt</span><span class="p">(</span><span class="nx">stringToBigInt</span><span class="p">(</span><span class="nx">cypherText</span><span class="p">),</span><span class="w"> </span><span class="nx">kp</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>We can encode any object as a string (and decode back strings to objects):</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">encrypt</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">obj</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">encryptString</span><span class="p">(</span><span class="nb">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">obj</span><span class="p">),</span><span class="w"> </span><span class="nx">kp</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">decrypt</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">cypherText</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="o">:</span><span class="w"> </span><span class="kt">SRAKeyPair</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">T</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nb">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">decryptString</span><span class="p">(</span><span class="nx">cypherText</span><span class="p">,</span><span class="w"> </span><span class="nx">kp</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>And that's it! We start with <code>randPrime()</code> to generate a large prime, then
use <code>generateKeyPair()</code> to derive \(E\) and \(D\) from it. We can then use this
<code>SRAKeyPair</code> with <code>encrypt()</code> and <code>decrypt()</code> to encrypt/decrypt objects using
the commutative SRA algorithm.</p>

<p>Here is a small example pulling everything together:</p>
<div class="highlight"><pre><span/><span class="c1">// Seed prime used by both players to generate keys</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">sharedPrime</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">randPrime</span><span class="p">();</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">aliceKP</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">generateKeyPair</span><span class="p">(</span><span class="nx">sharedPrime</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">bobKP</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">generateKeyPair</span><span class="p">(</span><span class="nx">sharedPrime</span><span class="p">);</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">card</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"Ace of spades"</span><span class="p">;</span>

<span class="c1">// Encrypt with Alice's key first, then Bob's</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">aliceEncrypted</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">encryptString</span><span class="p">(</span><span class="nx">card</span><span class="p">,</span><span class="w"> </span><span class="nx">aliceKP</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">aliceAndBobEncrypted</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">encryptString</span><span class="p">(</span><span class="nx">aliceEncrypted</span><span class="p">,</span><span class="w"> </span><span class="nx">bobKP</span><span class="p">);</span>

<span class="c1">// Decrypt with Alice's key first, then Bob's</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">bobEncrypted</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">decryptString</span><span class="p">(</span><span class="nx">aliceAndBobEncrypted</span><span class="p">,</span><span class="w"> </span><span class="nx">aliceKP</span><span class="p">);</span>
<span class="kd">const</span><span class="w"> </span><span class="nx">decrypted</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">decryptString</span><span class="p">(</span><span class="nx">bobEncrypted</span><span class="p">,</span><span class="w"> </span><span class="nx">bobKP</span><span class="p">);</span>

<span class="c1">// Prints "Ace of spades"</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">decrypted</span><span class="p">);</span>
</pre></div>

<h2>Summary</h2>

<ul>
<li>We went over a short overview of the SRA algorithm.</li>
<li>We looked at <code>BigInt</code> implementations for GCD, modulo inverse, and modulo
exponentiation.</li>
<li>Then we generated random large numbers by filling a buffer, and testing for
primality using the Miller-Rabin test.</li>
<li>With the math in place, we implemented a key generator for SRA (takin a
prime and deriving \(E\) and \(D\)).</li>
<li>We can encrypt/decrypt numbers by simply applying modulo exponentiation.</li>
<li>We can encrypt/decrypt any string by converting it to a <code>BigInt</code>, and more
generally any object by stringifying it.</li>
</ul>

<p>My work-in-progress Mental Poker Toolkit is <a href="https://github.com/vladris/mental-poker-toolkit">here</a>.
This post covered the <a href="https://github.com/vladris/mental-poker-toolkit/tree/main/packages/cryptography">cryptography package</a>.</p>
]]></description>
      <pubDate>Tue, 14 Mar 2023 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html</link>
      <guid>https://vladris.com/blog/2023/02/18/mental-poker-part-0-an-overview.html</guid>
      <title><![CDATA[Mental Poker Part 0: An Overview]]></title>
      <description><![CDATA[<h1>Mental Poker Part 0: An Overview</h1>

<p>I wrote previously about <a href="https://vladris.com/blog/2021/12/11/mental-poker.html">Mental Poker</a>,
how one can set up a game in a zero trust environment, and how this could be
implemented using <a href="https://fluidframework.com/">Fluid Framework</a>.</p>

<p>Since the previous post, I spent some more time prototyping an implementation
with a colleague and did a <a href="https://www.youtube.com/watch?v=F1gPTXAllxY">tech talk</a>
about it.</p>

<p>If you haven't read the previous post and are not familiar with Mental Poker,
the following won't make much sense. Please start there or by watching the
tech talk video.</p>

<p>The implementation consists of a few components:</p>

<ul>
<li>A Fluid Framework append-only list distributed data structure - Used for
tracking turns in a game.</li>
<li>Cryptography - An implementation of SRA (commutative encryption algorithm
required by Mental Poker) and digital signing (required for authenticating
messages from players).</li>
<li>Game client - A layer that abstracts communication between clients, with
an implementation on Fluid Framework.</li>
<li>A state machine - Used to model games (<strong>If I make this move I expect the
other player to make that move</strong>).</li>
<li>Recipes built on top of the state machine, like shuffling a deck of cards
using the steps described in my <a href="https://vladris.com/blog/2021/12/11/mental-poker.html">previous blog post</a>.</li>
</ul>

<p>At the time of writing, the append-only list distributed data structure is
ready, available on my GitHub as <a href="https://github.com/vladris/fluid-ledger">fluid-ledger</a>
and published on <a href="https://www.npmjs.com/package/fluid-ledger-dds">npm</a>.</p>

<p>The other components will all eventually end up in the
<a href="https://github.com/vladris/mental-poker-toolkit">mental-poker-toolkit</a> repo.</p>

<p>Some parts, like cryptography and the game client, I cleaned up and moved from
a private hackathon repo. Other parts, like the state machine, require major
rework, which I haven't gotten around to yet.</p>

<p>The plan is to provide a quality implementation with good documentation and
samples. A major difference between the hackathon proof of concept and this is
that the proof of concept implements a simple discard game while I'm hoping the
toolkit can support games with more than two players.</p>

<h2>Discard game</h2>

<p>Modeling a game like Poker is non-trivial. That said, a big part of the
complexity comes from the rules of the game itself. For a proof of concept of
Mental Poker, we didn't want to get in the weeds of Poker rules, rather
showcase the key ideas of how two players can shuffle a deck of cards, agree
on what order the cards end up in, while at the same time each being able
to maintain some private state (cards in hand). All of this done over a public
channel (Fluid Framework).</p>

<p>The game we modeled was simple: players draw a hand of cards, then take turns
discarding by number or suit. If a player can't discard (no matching number or
suit), they draw cards until they can discard. The player who discards their
whole hand first wins.</p>

<p>This prototype informed the components we had to build.</p>

<h2>A new distributed data structure</h2>

<p>Framework does not offer <q>out of the box</q> a data structure like the one needed
to model a sequence of moves. We ended up using <code>SharedObjectSequence</code>, a data
structure that was marked as deprecated and since removed from Fluid. In
general, the Fluid data structures that support lists are overkill for Mental
Poker as they support insertion and deletion of sequences of items at arbitrary
positions. For modeling a game, we just need an append only list - players take
turns and each <em>move</em> means appending something to the end of the list.</p>

<p>In fact, having an append-only list ensures that we don't run into issues like
a client unexpectedly inserting something in the middle of the list, which
doesn't make sense if we're modeling a sequence of moves in a game.</p>

<h2>Cryptography</h2>

<p>I was also not able to find a package providing commutative encryption. This is
a key requirement for the Mental Poker protocol but industry standard
cryptography algorithms do not have this property. I ended up implementing the
SRA algorithm from scratch, including a bunch of BigInt math. I still strongly
believe in the <em>don't roll your own crypto</em> rule, so please do not use my
implementation to play Poker for real money.</p>

<p>Besides encryption, we also need digital signatures. When a player joins a
game, they generate a public/private key pair and their first action is to post
their public key. All subsequent moves from that player are signed with the
private key, so other players can ensure the action is taken by the player
claiming to take that action, eliminating spoofing. Fortunately we were able to
use <code>Crypto.subtle</code> for this (see <a href="https://developer.mozilla.org/en-US/docs/Web/API/Crypto/subtle">Crypto Web API</a>).</p>

<h2>State machine</h2>

<p>Another interesting discovery was the state machine. A high-level game move,
like <em>I'm drawing a card from the top of the pile</em> translates into a message
exchange between the players:</p>

<ul>
<li><code>Alice</code>: I'm drawing a card from the top of the pile.</li>
<li><code>Bob</code>: Here is my key for that card.</li>
</ul>

<p>Shuffling cards, as described in the previous blog post, includes a longer
sequence of steps. We needed a way to express <q>I do <em>this</em>, then I expect the
other player to reply with <em>that</em></q>. We can use such a state machine to express
sequences of multiple moves to implement things like card shuffling.</p>

<p>The proof of concept state machine uses a queue of expected moves from the
other player to implement the game mechanics and Mental Poker protocol. For
example, for the Discard game, if it is the other player's turn, we expect
two things can happen: they either discard a card or draw a card.</p>

<p>If they discard a card, then they publish their encryption key for the card
which we can use to <em>see</em> the card (again, please refer to the previous
<a href="https://vladris.com/blog/2021/12/11/mental-poker.html">Mental Poker post</a> for
details on the protocol). Alternately, if they can't discard a card, they
need to draw a card, in which case we have to hand over our encryption key
for the card on top of the deck.</p>

<h2>Recipes</h2>

<p>Some of the rules captured in this state machine are specific to each game
implemented. Others though are simply steps in the Mental Poker protocol:
things like shuffling, drawing cards etc. are all modeled as <em>actions I take
and actions I expect the other player to follow up with</em>. I envision
expressing such known sequences as <q>recipes</q>, building blocks for games.</p>

<p>As I mentioned before, the proof of concept state machine implementation
requires some major rework. It needs to scale from two players to an arbitrary
number of players, and needs to support recipes, which it currently doesn't.
At the time of writing, this is one of the biggest chunks of pending work, and
considering this is a hobby project I work on when time permits, I currently
don't have a good sense of when I'll finish this. That said, a bunch of pieces
are already in decent shape and public, so I plan to write about them while
I continue working on finishing the toolkit.</p>

<h2>Mental Poker series</h2>

<p>In upcoming blog posts, I plan to cover the various pieces discussed above. The
components address different problems, and I find all of them quite interesting.
The problem space includes understanding how Fluid Framework distributed data
structures work internally, how to generate large prime numbers, and how to
model expected sequences of moves in a game among other things.</p>

<p>This post outlines the high level framing of the project. Following posts will
dive deep into specific aspects.</p>

<p>In terms of applications, as I mention in the tech talk, the term <em>games</em> is
pretty broad - we're not talking only about card games, but things like
auctions, lotteries, blind voting etc. All of these can be implemented using
Mental Poker as decentralized, zero-trust games.</p>
]]></description>
      <pubDate>Sat, 18 Feb 2023 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2023/01/07/notes-on-advent-of-code-2022.html</link>
      <guid>https://vladris.com/blog/2023/01/07/notes-on-advent-of-code-2022.html</guid>
      <title><![CDATA[Notes on Advent of Code 2022]]></title>
      <description><![CDATA[<h1>Notes on Advent of Code 2022</h1>

<p>I've been having fun solving <a href="https://adventofcode.com">Advent of Code</a> problems
every December for a few years now. Advent of Code is an advent calendar of
programming puzzles.</p>

<p>All my solutions are on my GitHub <a href="https://github.com/vladris/aoc">here</a>.
First, a quick disclaimer:</p>

<blockquote>
<p><strong>Disclaimer on my solutions</strong></p>

<p>I use Python because I find it easiest for this type of coding. I treat
solving these as a write-only exercise. I do it for the problem-solving bit,
so I don't comment the code &amp; once I find the solution I consider it <q>done</q> -
I donât revisit and try to optimize even though sometimes I strongly feel
like there is a better solution. I don't even share code between part 1 and
part 2 - once part 1 is solved, I copy/paste the solution and change it to
solve part 2, so each can be run independently. I also rarely use libraries,
and when I do it's some standard ones like <code>re</code>, <code>itertools</code>, or <code>math</code>. The
code has no comments and is littered with magic numbers and strange variable
names. This is not how I usually code, rather my decadent holiday indulgence.
I wasn't thinking I will end up writing a blog post discussing my solutions so
I would like to apologize for the code being hard to read.</p>
</blockquote>

<p>With that long disclaimer out of the way, let's talk Advent of Code 2022. I
figured I'll cover a few problems that seemed interesting to me during this
round, before they fade in my memory. The first couple of weeks are usually
easy, so I'll start from day 15.</p>

<h2>Day 15: Beacon Exclusion Zone</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/15">here</a>.</p>

<h3>Part 1</h3>

<p>Part 1 is pretty easy. We use taxicab geometry and for each sensor, we can find
its scan radius by computing the Manhattan distance between its coordinates and
the closest beacon it sees. Once we have this, we intersect each (taxicab)
circle with the row <code>y=2000000</code>. This gives as a bunch of segments defined by
<code>(x0, x1)</code> pairs.</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>

<span class="n">y</span><span class="p">,</span> <span class="n">segments</span> <span class="o">=</span> <span class="mi">2000000</span><span class="p">,</span> <span class="nb">set</span><span class="p">()</span>

<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">'Sensor at x=(-?\d+), y=(-?\d+).*x=(-?\d+), y=(-?\d+)$'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
    <span class="n">sx</span><span class="p">,</span> <span class="n">sy</span><span class="p">,</span> <span class="n">bx</span><span class="p">,</span> <span class="n">by</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">m</span><span class="o">.</span><span class="n">groups</span><span class="p">())</span>
    <span class="n">radius</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sx</span> <span class="o">-</span> <span class="n">bx</span><span class="p">)</span> <span class="o">+</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sy</span> <span class="o">-</span> <span class="n">by</span><span class="p">)</span>

    <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sy</span> <span class="o">-</span> <span class="n">y</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="n">radius</span><span class="p">:</span>
        <span class="n">segments</span><span class="o">.</span><span class="n">add</span><span class="p">(((</span><span class="n">sx</span> <span class="o">-</span> <span class="p">(</span><span class="n">radius</span> <span class="o">-</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sy</span> <span class="o">-</span> <span class="n">y</span><span class="p">)),</span>
                     <span class="p">(</span><span class="n">sx</span> <span class="o">+</span> <span class="p">(</span><span class="n">radius</span> <span class="o">-</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sy</span> <span class="o">-</span> <span class="n">y</span><span class="p">))))))</span>
</pre></div>

<p>We need to figure out where these overlap so we don't double-count so for each
pair of segments, if they intersect, we replace them by their union until no
segments intersect anymore. Then we simply sum the length
of each segment:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">intersect</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">s1</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="n">s2</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">and</span> <span class="n">s2</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="n">s1</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>

<span class="k">def</span><span class="w"> </span><span class="nf">union</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">(</span><span class="nb">min</span><span class="p">(</span><span class="n">s1</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">s2</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">max</span><span class="p">(</span><span class="n">s1</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">s2</span><span class="p">[</span><span class="mi">1</span><span class="p">]))</span>

<span class="n">done</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">done</span><span class="p">:</span>
    <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
    <span class="k">for</span> <span class="n">s1</span> <span class="ow">in</span> <span class="n">segments</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">s2</span> <span class="ow">in</span> <span class="n">segments</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">s1</span> <span class="o">==</span> <span class="n">s2</span><span class="p">:</span>
                <span class="k">continue</span>

            <span class="k">if</span> <span class="n">intersect</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">):</span>
                <span class="n">segments</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">s1</span><span class="p">)</span>
                <span class="n">segments</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">s2</span><span class="p">)</span>
                <span class="n">segments</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">union</span><span class="p">(</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">))</span>
                <span class="n">done</span> <span class="o">=</span> <span class="kc">False</span>
                <span class="k">break</span>

        <span class="k">if</span> <span class="ow">not</span> <span class="n">done</span><span class="p">:</span>
            <span class="k">break</span>

<span class="nb">print</span><span class="p">(</span><span class="nb">sum</span><span class="p">([</span><span class="n">s</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">s</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">segments</span><span class="p">]))</span>
</pre></div>

<h3>Part 2</h3>

<p>Part 2 is more interesting. We need to scan a quite large area (both <code>x</code> and <code>y</code>
between <code>0</code> and <code>4000000</code>). We know that all points except one are covered by at
least one sensor. We start from <code>(0, 0)</code> and scan like this: for each point,
find the first sensor that <q>sees</q> it (Manhattan distance from sensor &lt;= sensor
radius). If no scanner can see it, we found our point. Otherwise, again relying
on taxicab geometry, we can tell how many additional points to the right
(increasing <code>x</code>) are still in range of this sensor. We move <code>x</code> beyond these
(\(x = x_sensor + radius - abs(y_sensor - y) + 1\)). If <code>x</code> goes beyond
<code>4000000</code>, we reset it to <code>0</code> and increment <code>y</code>. This is not blazingly fast, but
does the job in a reasonable amount of time (around 20 seconds on my machine).</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>

<span class="n">sensors</span> <span class="o">=</span> <span class="p">[]</span>

<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="s1">'Sensor at x=(-?\d+), y=(-?\d+).*x=(-?\d+), y=(-?\d+)$'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
    <span class="n">sx</span><span class="p">,</span> <span class="n">sy</span><span class="p">,</span> <span class="n">bx</span><span class="p">,</span> <span class="n">by</span> <span class="o">=</span> <span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">m</span><span class="o">.</span><span class="n">groups</span><span class="p">())</span>
    <span class="n">radius</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sx</span> <span class="o">-</span> <span class="n">bx</span><span class="p">)</span> <span class="o">+</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sy</span> <span class="o">-</span> <span class="n">by</span><span class="p">)</span>
    <span class="n">sensors</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">sx</span><span class="p">,</span> <span class="n">sy</span><span class="p">,</span> <span class="n">radius</span><span class="p">))</span>

<span class="k">def</span><span class="w"> </span><span class="nf">in_range</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">sensor</span> <span class="ow">in</span> <span class="n">sensors</span><span class="p">:</span>
        <span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sensor</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">x</span><span class="p">)</span> <span class="o">+</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sensor</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">y</span><span class="p">)</span> <span class="o">&lt;=</span> <span class="n">sensor</span><span class="p">[</span><span class="mi">2</span><span class="p">]:</span>
            <span class="k">return</span> <span class="kc">True</span><span class="p">,</span> <span class="n">sensor</span>

    <span class="k">return</span> <span class="kc">False</span><span class="p">,</span> <span class="kc">None</span>

<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
    <span class="n">found</span><span class="p">,</span> <span class="n">sensor</span> <span class="o">=</span> <span class="n">in_range</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
    <span class="k">if</span> <span class="ow">not</span> <span class="n">found</span><span class="p">:</span>
        <span class="k">break</span>

    <span class="n">x</span> <span class="o">=</span> <span class="n">sensor</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">sensor</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">-</span> <span class="nb">abs</span><span class="p">(</span><span class="n">sensor</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">y</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
    <span class="k">if</span> <span class="n">x</span> <span class="o">&gt;</span> <span class="mi">4_000_000</span><span class="p">:</span>
        <span class="n">x</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">y</span> <span class="o">+=</span> <span class="mi">1</span>

<span class="nb">print</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="mi">4_000_000</span> <span class="o">+</span> <span class="n">y</span><span class="p">)</span>
</pre></div>

<h2>Day 16: Proboscidea Volcanium</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/16">here</a>.</p>

<h3>Part 1</h3>

<p>Part 1 is again pretty easy: we can model the valves and tunnels as a graph,
then use the Floyd-Warshall algorithm to find the distances between each pair of
valves:</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>

<span class="n">dist</span><span class="p">,</span> <span class="n">flows</span><span class="p">,</span> <span class="n">to_open</span> <span class="o">=</span> <span class="p">{},</span> <span class="p">{},</span> <span class="nb">set</span><span class="p">()</span>

<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span>
        <span class="s1">'Valve (\w+) has flow rate=(\d+); tunnels? leads? to valves? (.*)$'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
    <span class="n">src</span><span class="p">,</span> <span class="n">flow</span><span class="p">,</span> <span class="o">*</span><span class="n">dst</span> <span class="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">groups</span><span class="p">()</span>
    <span class="n">dst</span> <span class="o">=</span> <span class="p">[</span><span class="n">d</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">dst</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">)]</span>
    <span class="n">dist</span><span class="p">[</span><span class="n">src</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span><span class="n">d</span><span class="p">:</span> <span class="mi">1</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">dst</span><span class="p">}</span> <span class="o">|</span> <span class="p">{</span><span class="n">src</span><span class="p">:</span> <span class="mi">0</span><span class="p">}</span>
    <span class="n">flows</span><span class="p">[</span><span class="n">src</span><span class="p">]</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">flow</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">flows</span><span class="p">[</span><span class="n">src</span><span class="p">]</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">to_open</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">src</span><span class="p">)</span>

<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">j</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">]:</span>
            <span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1000</span>

<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">dist</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">dist</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">j</span><span class="p">]:</span>
                <span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">dist</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">k</span><span class="p">]</span> <span class="o">+</span> <span class="n">dist</span><span class="p">[</span><span class="n">k</span><span class="p">][</span><span class="n">j</span><span class="p">]</span>
</pre></div>

<p>We can then search for the best solution recursively: we start from <code>AA</code> and
keep track of which valves we opened (none for starters). Then at each step,
pick one of the unopened valves. If we have enough time to reach them, recurse
with updated location and set of opened nodes. We also compute the total
pressure released so far at each step and keep track of the highest value we
found. This gives us the solution.</p>
<div class="highlight"><pre><span/><span class="n">best</span> <span class="o">=</span> <span class="mi">0</span>

<span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="n">current</span><span class="o">=</span><span class="s1">'AA'</span><span class="p">,</span> <span class="n">opened</span><span class="o">=</span><span class="nb">set</span><span class="p">(),</span> <span class="n">time</span><span class="o">=</span><span class="mi">30</span><span class="p">,</span> <span class="n">score</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">best</span>

    <span class="n">score</span> <span class="o">+=</span> <span class="n">time</span> <span class="o">*</span> <span class="n">flows</span><span class="p">[</span><span class="n">current</span><span class="p">]</span>

    <span class="k">if</span> <span class="n">score</span> <span class="o">&gt;=</span> <span class="n">best</span><span class="p">:</span>
        <span class="n">best</span> <span class="o">=</span> <span class="n">score</span>

    <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">to_open</span> <span class="o">-</span> <span class="n">opened</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">time</span> <span class="o">-</span> <span class="n">dist</span><span class="p">[</span><span class="n">current</span><span class="p">][</span><span class="n">node</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">search</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">opened</span> <span class="o">|</span> <span class="p">{</span><span class="n">node</span><span class="p">},</span> <span class="n">time</span> <span class="o">-</span>
                   <span class="n">dist</span><span class="p">[</span><span class="n">current</span><span class="p">][</span><span class="n">node</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">score</span><span class="p">)</span>

<span class="n">search</span><span class="p">()</span>

<span class="nb">print</span><span class="p">(</span><span class="n">best</span><span class="p">)</span>
</pre></div>

<h3>Part 2</h3>

<p>Part 2 is more fun. We now have an elephant to help us, which makes it a bit
more complicated. My solution now keeps track of a few more things: which valve
am I headed to and how many more minutes I have to get there; which valve is the
elephant headed to and how many more minutes until it gets there. We both start
at <code>AA</code> with an ETA of <code>0</code>. Then for each node, if my ETA is 0, I'll be heading
that way. If not, the elephant will be heading there. But since we're dealing
with two ETAs, we need to figure out which of us will reach their destination
first, and recurse to that time.</p>
<div class="highlight"><pre><span/><span class="n">best</span> <span class="o">=</span> <span class="mi">0</span>

<span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="n">me</span><span class="o">=</span><span class="p">(</span><span class="s1">'AA'</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">elephant</span><span class="o">=</span><span class="p">(</span><span class="s1">'AA'</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">opened</span><span class="o">=</span><span class="nb">set</span><span class="p">(),</span> <span class="n">time</span><span class="o">=</span><span class="mi">26</span><span class="p">,</span> <span class="n">score</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">best</span>

    <span class="k">if</span> <span class="n">score</span> <span class="o">&gt;</span> <span class="n">best</span><span class="p">:</span>
        <span class="n">best</span> <span class="o">=</span> <span class="n">score</span>

    <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">to_open</span> <span class="o">-</span> <span class="n">opened</span><span class="p">:</span>
        <span class="n">me_next</span><span class="p">,</span> <span class="n">elephant_next</span><span class="p">,</span> <span class="n">score_next</span> <span class="o">=</span> <span class="n">me</span><span class="p">,</span> <span class="n">elephant</span><span class="p">,</span> <span class="n">score</span>
        <span class="k">if</span> <span class="n">me</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">me_next</span> <span class="o">=</span> <span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">dist</span><span class="p">[</span><span class="n">me</span><span class="p">[</span><span class="mi">0</span><span class="p">]][</span><span class="n">node</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
            <span class="n">score_next</span> <span class="o">+=</span> <span class="p">(</span><span class="n">time</span> <span class="o">-</span> <span class="n">dist</span><span class="p">[</span><span class="n">me</span><span class="p">[</span><span class="mi">0</span><span class="p">]][</span><span class="n">node</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">flows</span><span class="p">[</span><span class="n">node</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">elephant_next</span> <span class="o">=</span> <span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">dist</span><span class="p">[</span><span class="n">elephant</span><span class="p">[</span><span class="mi">0</span><span class="p">]][</span><span class="n">node</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
            <span class="n">score_next</span> <span class="o">+=</span> <span class="p">(</span><span class="n">time</span> <span class="o">-</span> <span class="n">dist</span><span class="p">[</span><span class="n">elephant</span><span class="p">[</span><span class="mi">0</span><span class="p">]][</span><span class="n">node</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">flows</span><span class="p">[</span><span class="n">node</span><span class="p">]</span>

        <span class="n">dt</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">me_next</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">elephant_next</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="n">me_next</span> <span class="o">=</span> <span class="p">(</span><span class="n">me_next</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">me_next</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">dt</span><span class="p">)</span>
        <span class="n">elephant_next</span> <span class="o">=</span> <span class="p">(</span><span class="n">elephant_next</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">elephant_next</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">dt</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">time</span> <span class="o">-</span> <span class="n">dt</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">search</span><span class="p">(</span><span class="n">me_next</span><span class="p">,</span> <span class="n">elephant_next</span><span class="p">,</span> <span class="n">opened</span> <span class="o">|</span>
                   <span class="p">{</span><span class="n">node</span><span class="p">},</span> <span class="n">time</span> <span class="o">-</span> <span class="n">dt</span><span class="p">,</span> <span class="n">score_next</span><span class="p">)</span>

<span class="n">search</span><span class="p">()</span>

<span class="nb">print</span><span class="p">(</span><span class="n">best</span><span class="p">)</span>
</pre></div>

<p>This works but takes a long time, so I added some caching: since both the
elephant and I move around a bunch, we can cache the score for each combination
of my destination and ETA, the elephant's destination and ETA, and the time. If
at a given minute, both the elephant and I were already in this situation but
with a better score, we no longer need to keep searching this branch as we
already found a better solution. This prunes enough of the search tree to easily
find the answer. Updated search with cache:</p>
<div class="highlight"><pre><span/><span class="n">best</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">cache</span> <span class="o">=</span> <span class="p">{}</span>

<span class="k">def</span><span class="w"> </span><span class="nf">search</span><span class="p">(</span><span class="n">me</span><span class="o">=</span><span class="p">(</span><span class="s1">'AA'</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">elephant</span><span class="o">=</span><span class="p">(</span><span class="s1">'AA'</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">opened</span><span class="o">=</span><span class="nb">set</span><span class="p">(),</span> <span class="n">time</span><span class="o">=</span><span class="mi">26</span><span class="p">,</span> <span class="n">score</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
    <span class="k">global</span> <span class="n">best</span>

    <span class="k">if</span> <span class="n">score</span> <span class="o">&gt;</span> <span class="n">best</span><span class="p">:</span>
        <span class="n">best</span> <span class="o">=</span> <span class="n">score</span>

    <span class="n">key</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">me</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">elephant</span><span class="p">)</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">time</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">cache</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="n">score</span><span class="p">:</span>
            <span class="k">return</span>

    <span class="n">cache</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">score</span>

    <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">to_open</span> <span class="o">-</span> <span class="n">opened</span><span class="p">:</span>
        <span class="n">me_next</span><span class="p">,</span> <span class="n">elephant_next</span><span class="p">,</span> <span class="n">score_next</span> <span class="o">=</span> <span class="n">me</span><span class="p">,</span> <span class="n">elephant</span><span class="p">,</span> <span class="n">score</span>
        <span class="k">if</span> <span class="n">me</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">me_next</span> <span class="o">=</span> <span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">dist</span><span class="p">[</span><span class="n">me</span><span class="p">[</span><span class="mi">0</span><span class="p">]][</span><span class="n">node</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
            <span class="n">score_next</span> <span class="o">+=</span> <span class="p">(</span><span class="n">time</span> <span class="o">-</span> <span class="n">dist</span><span class="p">[</span><span class="n">me</span><span class="p">[</span><span class="mi">0</span><span class="p">]][</span><span class="n">node</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">flows</span><span class="p">[</span><span class="n">node</span><span class="p">]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">elephant_next</span> <span class="o">=</span> <span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">dist</span><span class="p">[</span><span class="n">elephant</span><span class="p">[</span><span class="mi">0</span><span class="p">]][</span><span class="n">node</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
            <span class="n">score_next</span> <span class="o">+=</span> <span class="p">(</span><span class="n">time</span> <span class="o">-</span> <span class="n">dist</span><span class="p">[</span><span class="n">elephant</span><span class="p">[</span><span class="mi">0</span><span class="p">]][</span><span class="n">node</span><span class="p">]</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">*</span> <span class="n">flows</span><span class="p">[</span><span class="n">node</span><span class="p">]</span>

        <span class="n">dt</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">me_next</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">elephant_next</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
        <span class="n">me_next</span> <span class="o">=</span> <span class="p">(</span><span class="n">me_next</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">me_next</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">dt</span><span class="p">)</span>
        <span class="n">elephant_next</span> <span class="o">=</span> <span class="p">(</span><span class="n">elephant_next</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">elephant_next</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">dt</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">time</span> <span class="o">-</span> <span class="n">dt</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">search</span><span class="p">(</span><span class="n">me_next</span><span class="p">,</span> <span class="n">elephant_next</span><span class="p">,</span> <span class="n">opened</span> <span class="o">|</span>
                   <span class="p">{</span><span class="n">node</span><span class="p">},</span> <span class="n">time</span> <span class="o">-</span> <span class="n">dt</span><span class="p">,</span> <span class="n">score_next</span><span class="p">)</span>

<span class="n">search</span><span class="p">()</span>

<span class="nb">print</span><span class="p">(</span><span class="n">best</span><span class="p">)</span>
</pre></div>

<h2>Day 17: Pyroclastic Flow</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/17">here</a>.</p>

<h3>Part 1</h3>

<p>For part 1 we can simply simulate the falling blocks and find the answer. This gives us some of the building blocks needed for part 2.</p>
<div class="highlight"><pre><span/><span class="n">jets</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>

<span class="n">rocks</span> <span class="o">=</span> <span class="p">[{(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)},</span> 
         <span class="p">{(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">)},</span>
         <span class="p">{(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">)},</span>
         <span class="p">{(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">)},</span>
         <span class="p">{(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)}]</span>

<span class="n">grid</span> <span class="o">=</span> <span class="nb">set</span><span class="p">({(</span><span class="n">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">8</span><span class="p">)})</span>

<span class="k">def</span><span class="w"> </span><span class="nf">intersects</span><span class="p">(</span><span class="n">rock</span><span class="p">,</span> <span class="n">grid</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">rock</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">block</span> <span class="ow">in</span> <span class="n">grid</span> <span class="ow">or</span> <span class="n">block</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">block</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="mi">8</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">True</span>
    <span class="k">return</span> <span class="kc">False</span>

<span class="k">def</span><span class="w"> </span><span class="nf">move</span><span class="p">(</span><span class="n">rock</span><span class="p">,</span> <span class="n">dx</span><span class="p">,</span> <span class="n">dy</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">{(</span><span class="n">i</span> <span class="o">+</span> <span class="n">dx</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="n">dy</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span> <span class="ow">in</span> <span class="n">rock</span><span class="p">}</span>

<span class="n">rock_i</span><span class="p">,</span> <span class="n">jet_i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2022</span><span class="p">):</span>
    <span class="n">top</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">grid</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">pt</span><span class="p">:</span> <span class="n">pt</span><span class="p">[</span><span class="mi">1</span><span class="p">])[</span><span class="mi">1</span><span class="p">]</span>
    <span class="n">rock</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">rocks</span><span class="p">[</span><span class="n">rock_i</span><span class="p">],</span> <span class="mi">3</span><span class="p">,</span> <span class="n">top</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span>

    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">new_pos</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">rock</span><span class="p">,</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">jets</span><span class="p">[</span><span class="n">jet_i</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'&gt;'</span> <span class="k">else</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">jet_i</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="n">jet_i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">jets</span><span class="p">):</span>
            <span class="n">jet_i</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">intersects</span><span class="p">(</span><span class="n">new_pos</span><span class="p">,</span> <span class="n">grid</span><span class="p">):</span>
            <span class="n">rock</span> <span class="o">=</span> <span class="n">new_pos</span>
        <span class="n">new_pos</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">rock</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">intersects</span><span class="p">(</span><span class="n">new_pos</span><span class="p">,</span> <span class="n">grid</span><span class="p">):</span>
            <span class="k">break</span>
        <span class="n">rock</span> <span class="o">=</span> <span class="n">new_pos</span>

    <span class="n">grid</span> <span class="o">|=</span> <span class="n">rock</span>
    <span class="n">rock_i</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">if</span> <span class="n">rock_i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">rocks</span><span class="p">):</span>
        <span class="n">rock_i</span> <span class="o">=</span> <span class="mi">0</span>

<span class="nb">print</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">grid</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">pt</span><span class="p">:</span> <span class="n">pt</span><span class="p">[</span><span class="mi">1</span><span class="p">])[</span><span class="mi">1</span><span class="p">])</span>
</pre></div>

<h3>Part 2</h3>

<p>Part 2 makes it obvious simulating everything is not an option as we need to
look at a thousand billion rocks. The key here is to find a pattern: we are
bound to end up simulating the same rock and initial move instruction over and
over. If we do and we see the same gain in height between repeats, it means we
found our repeating pattern. We know that starting from this position, we have a
period of length <code>period</code> in which our tower of rocks grows by <code>growth</code>. We
subtract the number of rocks we already simulated from 1000000000000, we divide
by <code>period</code> and multiply by <code>growth</code>. We'll call this <code>delta_top</code>.</p>

<p>We are close to the final answer. The only thing left to do is simulate a few
more steps: 1000000000000 minus the number of rocks we already simulated modulo
<code>period</code>. Now we get the height of the top of the tower we simulated and add
<code>delta_top</code> to it to find the final answer.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">top</span><span class="p">():</span>
    <span class="k">return</span> <span class="nb">max</span><span class="p">(</span><span class="n">grid</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="k">lambda</span> <span class="n">pt</span><span class="p">:</span> <span class="n">pt</span><span class="p">[</span><span class="mi">1</span><span class="p">])[</span><span class="mi">1</span><span class="p">]</span>

<span class="n">rock_i</span><span class="p">,</span> <span class="n">jet_i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="n">cache</span><span class="p">,</span> <span class="n">delta_top</span> <span class="o">=</span> <span class="p">{},</span> <span class="mi">0</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10_000</span><span class="p">:</span>
    <span class="n">rock</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">rocks</span><span class="p">[</span><span class="n">rock_i</span><span class="p">],</span> <span class="mi">3</span><span class="p">,</span> <span class="n">top</span><span class="p">()</span> <span class="o">+</span> <span class="mi">4</span><span class="p">)</span>

    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">new_pos</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">rock</span><span class="p">,</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">jets</span><span class="p">[</span><span class="n">jet_i</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'&gt;'</span> <span class="k">else</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="n">jet_i</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="n">jet_i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">jets</span><span class="p">):</span>
            <span class="n">jet_i</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">intersects</span><span class="p">(</span><span class="n">new_pos</span><span class="p">,</span> <span class="n">grid</span><span class="p">):</span>
            <span class="n">rock</span> <span class="o">=</span> <span class="n">new_pos</span>
        <span class="n">new_pos</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">rock</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">intersects</span><span class="p">(</span><span class="n">new_pos</span><span class="p">,</span> <span class="n">grid</span><span class="p">):</span>
            <span class="k">break</span>
        <span class="n">rock</span> <span class="o">=</span> <span class="n">new_pos</span>

    <span class="n">grid</span> <span class="o">|=</span> <span class="n">rock</span>
    <span class="n">rock_i</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">if</span> <span class="n">rock_i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">rocks</span><span class="p">):</span>
        <span class="n">rock_i</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
    
    <span class="k">if</span> <span class="ow">not</span> <span class="n">delta_top</span><span class="p">:</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">rock_i</span><span class="p">,</span> <span class="n">jet_i</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">cache</span><span class="p">:</span>
            <span class="n">cache</span><span class="p">[(</span><span class="n">rock_i</span><span class="p">,</span> <span class="n">jet_i</span><span class="p">)]</span> <span class="o">=</span> <span class="p">[]</span>
        <span class="n">c</span> <span class="o">=</span> <span class="n">cache</span><span class="p">[(</span><span class="n">rock_i</span><span class="p">,</span> <span class="n">jet_i</span><span class="p">)]</span>
        <span class="n">c</span><span class="o">.</span><span class="n">append</span><span class="p">([</span><span class="n">i</span><span class="p">,</span> <span class="n">top</span><span class="p">()])</span>
        <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">c</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">c</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">c</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">c</span><span class="p">[</span><span class="o">-</span><span class="mi">3</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
            <span class="n">period</span><span class="p">,</span> <span class="n">growth</span> <span class="o">=</span> <span class="n">c</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">c</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">c</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span> <span class="n">c</span><span class="p">[</span><span class="o">-</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
            <span class="n">delta_top</span> <span class="o">=</span> <span class="p">(</span><span class="mi">1_000_000_000_000</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">//</span> <span class="n">period</span> <span class="o">*</span> <span class="n">growth</span>
            <span class="n">i</span> <span class="o">=</span> <span class="mi">10_000</span> <span class="o">-</span> <span class="p">(</span><span class="mi">1_000_000_000_000</span> <span class="o">-</span> <span class="n">i</span><span class="p">)</span> <span class="o">%</span> <span class="n">period</span>

<span class="nb">print</span><span class="p">(</span><span class="n">top</span><span class="p">()</span> <span class="o">+</span> <span class="n">delta_top</span><span class="p">)</span>
</pre></div>

<h2>Day 18: Boiling Boulders</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/18">here</a>.</p>

<h3>Part 1</h3>

<p>Part is trivial so I won't discuss it here.</p>

<h3>Part 2</h3>

<p>Part 2 is also very easy, but I found a really neat solution worth sharing:
since all boulders are within <code>(0, 0, 0)</code> and <code>(20, 20, 20)</code>, I look at a grid
encompassing everything (<code>(-1, -1, -1) to (21, 21, 21)</code>) and starting from <code>(-1,
-1, -1)</code>, flood fill. We use a queue and at each step we dequeue a triple of
coordinates. If already visited or out of bounds, we ignore it and continue.
Otherwise if it is a boulder, it means we found a new surface area. We mark
these coordinates as visited and enqueue all the neighbors. I like how whenever
we run into a boulder gives us exactly the area we are looking for. The full
solution is:</p>
<div class="highlight"><pre><span/><span class="n">cubes</span> <span class="o">=</span> <span class="p">[</span><span class="nb">tuple</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">l</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">)))</span> <span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">()]</span>

<span class="n">visited</span><span class="p">,</span> <span class="n">queue</span><span class="p">,</span> <span class="n">area</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(),</span> <span class="p">[(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)],</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">queue</span><span class="p">:</span>
    <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">)</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">)</span> <span class="ow">in</span> <span class="n">visited</span><span class="p">:</span>
        <span class="k">continue</span>

    <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span> <span class="o">&lt;=</span> <span class="n">x</span> <span class="o">&lt;=</span> <span class="mi">22</span> <span class="ow">and</span> <span class="o">-</span><span class="mi">1</span> <span class="o">&lt;=</span> <span class="n">y</span> <span class="o">&lt;=</span> <span class="mi">22</span> <span class="ow">and</span> <span class="o">-</span><span class="mi">1</span> <span class="o">&lt;=</span> <span class="n">z</span> <span class="o">&lt;=</span> <span class="mi">22</span><span class="p">):</span>
        <span class="k">continue</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">)</span> <span class="ow">in</span> <span class="n">cubes</span><span class="p">:</span>
        <span class="n">area</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">continue</span>

    <span class="n">visited</span><span class="o">.</span><span class="n">add</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">))</span>
    <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">))</span>
    <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">))</span>
    <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">z</span><span class="p">))</span>
    <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">z</span><span class="p">))</span>
    <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">-</span> <span class="mi">1</span><span class="p">))</span>
    <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>

<span class="nb">print</span><span class="p">(</span><span class="n">area</span><span class="p">)</span>
</pre></div>

<h2>Day 19: Not Enough Minerals</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/19">here</a>.</p>

<p>I used the same solution for part 1 and part 2: a recursive search where we keep
track of the bots and resources we have, and the time. The problem is it takes
too long to simulate minute by minute. If we try deciding at each minute whether
to build any of the bots we can build or keep collecting resources, then recurse
to next minute, we end up with too much combinatorial complexity. My solution
instead does something like this: for the current moment in time, for each type
of robot, say we want to build that one next - based on costs and available
resources, we can calculate how many minutes from now that robot be built. We
can then recurse (jump ahead in time) there updating available resources, since
we know other robots won't be built until then.</p>

<p>As an additional optimization, we can keep track of how many geodes we collected
at each minute and if our current search has fewer geodes, it means we already
found a better solution and it is not worth going down this branch. There's
probably smarter caching/pruning we can do but this seems to be good enough.</p>

<p>This tames the combinatorial complexity enough to get a reasonable run time and
going from simulating 24 minutes in part 1 to simulating 32 minutes for fewer
blueprints in part 2 doesn't seem to require changing the algorithm. Both parts
take around 2 minutes to run. It can probably be optimize further.</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">math</span>

<span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="n">bots</span><span class="p">,</span> <span class="n">costs</span><span class="p">,</span> <span class="n">resources</span><span class="p">,</span> <span class="n">time</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">best</span><span class="p">[</span><span class="n">time</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">resources</span><span class="p">[</span><span class="mi">3</span><span class="p">]:</span>
        <span class="k">return</span>

    <span class="n">best</span><span class="p">[</span><span class="n">time</span><span class="p">]</span> <span class="o">=</span> <span class="n">resources</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>

    <span class="k">if</span> <span class="n">time</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="k">for</span> <span class="n">bot_type</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">):</span>
        <span class="n">dt</span> <span class="o">=</span> <span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">((</span><span class="n">costs</span><span class="p">[</span><span class="n">bot_type</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">-</span> <span class="n">resources</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">/</span> <span class="n">bots</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
        <span class="k">if</span> <span class="n">bot_type</span> <span class="o">&gt;=</span> <span class="mi">2</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">bots</span><span class="p">[</span><span class="n">bot_type</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                <span class="k">continue</span>

            <span class="n">dt</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span> <span class="n">math</span><span class="o">.</span><span class="n">ceil</span><span class="p">((</span><span class="n">costs</span><span class="p">[</span><span class="n">bot_type</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">-</span>
                                    <span class="n">resources</span><span class="p">[</span><span class="n">bot_type</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span> <span class="o">/</span> <span class="n">bots</span><span class="p">[</span><span class="n">bot_type</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]))</span>

        <span class="n">dt</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">dt</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">time</span> <span class="o">&lt;</span> <span class="n">dt</span><span class="p">:</span>
            <span class="k">continue</span>

        <span class="n">new_resources</span> <span class="o">=</span> <span class="p">[</span><span class="n">resources</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">bots</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">dt</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">)]</span>
        <span class="n">new_resources</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">-=</span> <span class="n">costs</span><span class="p">[</span><span class="n">bot_type</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">bot_type</span> <span class="o">&gt;=</span> <span class="mi">2</span><span class="p">:</span>
            <span class="n">new_resources</span><span class="p">[</span><span class="n">bot_type</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">-=</span> <span class="n">costs</span><span class="p">[</span><span class="n">bot_type</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>

        <span class="n">bots</span><span class="p">[</span><span class="n">bot_type</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">run</span><span class="p">(</span><span class="n">bots</span><span class="p">,</span> <span class="n">costs</span><span class="p">,</span> <span class="n">new_resources</span><span class="p">,</span> <span class="n">time</span> <span class="o">-</span> <span class="n">dt</span><span class="p">)</span>
        <span class="n">bots</span><span class="p">[</span><span class="n">bot_type</span><span class="p">]</span> <span class="o">-=</span> <span class="mi">1</span>

<span class="n">score</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">()[:</span><span class="mi">3</span><span class="p">]:</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span>
        <span class="s1">'.*(\d+) ore.*(\d+) ore.*(\d+) ore and (\d+) clay.*(\d+) ore and (\d+) obsidian'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
    <span class="n">costs</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">m</span><span class="o">.</span><span class="n">groups</span><span class="p">()))</span>

    <span class="n">costs</span> <span class="o">=</span> <span class="p">[[</span><span class="n">costs</span><span class="p">[</span><span class="mi">0</span><span class="p">]],</span> <span class="p">[</span><span class="n">costs</span><span class="p">[</span><span class="mi">1</span><span class="p">]],</span> <span class="p">[</span>
        <span class="n">costs</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">costs</span><span class="p">[</span><span class="mi">3</span><span class="p">]],</span> <span class="p">[</span><span class="n">costs</span><span class="p">[</span><span class="mi">4</span><span class="p">],</span> <span class="n">costs</span><span class="p">[</span><span class="mi">5</span><span class="p">]]]</span>

    <span class="n">best</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">33</span>

    <span class="n">run</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">],</span> <span class="n">costs</span><span class="p">,</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">32</span><span class="p">)</span>

    <span class="n">score</span> <span class="o">*=</span> <span class="n">best</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>

<span class="nb">print</span><span class="p">(</span><span class="n">score</span><span class="p">)</span>
</pre></div>

<h2>Day 20: Grove Positioning System</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/20">here</a>.</p>

<p>Day 20 was very easy so I won't cover it here.</p>

<h2>Day 21: Monkey Math</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/21">here</a>.</p>

<h3>Part 1</h3>

<p>Another easy one. For part 1, we parse the input in an expression tree (with
values at leaf nodes and operators at non-leaf nodes) and we recursively
evaluate it from root.</p>
<div class="highlight"><pre><span/><span class="n">tree</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
    <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">': '</span><span class="p">)</span>
    <span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">value</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
    <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>


<span class="k">def</span><span class="w"> </span><span class="nf">get</span><span class="p">(</span><span class="n">key</span><span class="p">):</span>
    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">],</span> <span class="nb">int</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
    
    <span class="n">v1</span><span class="p">,</span> <span class="n">v2</span> <span class="o">=</span> <span class="n">get</span><span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">0</span><span class="p">]),</span> <span class="n">get</span><span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">2</span><span class="p">])</span>

    <span class="k">match</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
        <span class="k">case</span> <span class="s1">'+'</span><span class="p">:</span> <span class="k">return</span> <span class="n">v1</span> <span class="o">+</span> <span class="n">v2</span>
        <span class="k">case</span> <span class="s1">'-'</span><span class="p">:</span> <span class="k">return</span> <span class="n">v1</span> <span class="o">-</span> <span class="n">v2</span>
        <span class="k">case</span> <span class="s1">'*'</span><span class="p">:</span> <span class="k">return</span> <span class="n">v1</span> <span class="o">*</span> <span class="n">v2</span>
        <span class="k">case</span> <span class="s1">'/'</span><span class="p">:</span> <span class="k">return</span> <span class="n">v1</span> <span class="o">//</span> <span class="n">v2</span>

<span class="nb">print</span><span class="p">(</span><span class="n">get</span><span class="p">(</span><span class="s1">'root'</span><span class="p">))</span>
</pre></div>

<h3>Part 2</h3>

<p>Part 2 effectively makes the root be <code>==</code> and asks us to find the value for the
<code>humn</code> node. For this, we can update our recursive evaluation to either compute
a value or return <code>None</code> if <code>humn</code> is part of the subtree we're trying to
evaluate (so if either left or right subtree evaluates to <code>None</code>, return
<code>None</code>). We add another recursive function <code>solve()</code> which takes a node and an
expected value (we expect the node to end up equal to the value) then we can
recursively solve: evaluate left and right. Depending on which of them returns
<code>None</code>, we recurse down that subtree with an updated expected value. For
example, if we expect <code>left + right</code> to be <code>10</code> and we get <code>5</code> and <code>None</code> back,
then we recurse down the <code>right</code> subtree, with an expected value of <code>10 - left</code>.</p>
<div class="highlight"><pre><span/><span class="n">tree</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">():</span>
    <span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">': '</span><span class="p">)</span>
    <span class="n">value</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">value</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">value</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
    <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>

<span class="k">def</span><span class="w"> </span><span class="nf">get</span><span class="p">(</span><span class="n">key</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">==</span> <span class="kc">None</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">],</span> <span class="nb">int</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
    
    <span class="n">v1</span><span class="p">,</span> <span class="n">v2</span> <span class="o">=</span> <span class="n">get</span><span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">0</span><span class="p">]),</span> <span class="n">get</span><span class="p">(</span><span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">2</span><span class="p">])</span>

    <span class="k">if</span> <span class="n">v1</span> <span class="o">==</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">v2</span> <span class="o">==</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="kc">None</span>

    <span class="k">match</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
        <span class="k">case</span> <span class="s1">'+'</span><span class="p">:</span> <span class="k">return</span> <span class="n">v1</span> <span class="o">+</span> <span class="n">v2</span>
        <span class="k">case</span> <span class="s1">'-'</span><span class="p">:</span> <span class="k">return</span> <span class="n">v1</span> <span class="o">-</span> <span class="n">v2</span>
        <span class="k">case</span> <span class="s1">'*'</span><span class="p">:</span> <span class="k">return</span> <span class="n">v1</span> <span class="o">*</span> <span class="n">v2</span>
        <span class="k">case</span> <span class="s1">'/'</span><span class="p">:</span> <span class="k">return</span> <span class="n">v1</span> <span class="o">//</span> <span class="n">v2</span>


<span class="k">def</span><span class="w"> </span><span class="nf">solve</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">eq</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">==</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">eq</span>

    <span class="n">k1</span><span class="p">,</span> <span class="n">k2</span> <span class="o">=</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">0</span><span class="p">],</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span>
    <span class="n">v1</span><span class="p">,</span> <span class="n">v2</span> <span class="o">=</span> <span class="n">get</span><span class="p">(</span><span class="n">k1</span><span class="p">),</span> <span class="n">get</span><span class="p">(</span><span class="n">k2</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">v1</span> <span class="o">==</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">match</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
            <span class="k">case</span> <span class="s1">'+'</span><span class="p">:</span> <span class="k">return</span> <span class="n">solve</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">eq</span> <span class="o">-</span> <span class="n">v2</span><span class="p">)</span>
            <span class="k">case</span> <span class="s1">'-'</span><span class="p">:</span> <span class="k">return</span> <span class="n">solve</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">eq</span> <span class="o">+</span> <span class="n">v2</span><span class="p">)</span>
            <span class="k">case</span> <span class="s1">'*'</span><span class="p">:</span> <span class="k">return</span> <span class="n">solve</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">eq</span> <span class="o">//</span> <span class="n">v2</span><span class="p">)</span>
            <span class="k">case</span> <span class="s1">'/'</span><span class="p">:</span> <span class="k">return</span> <span class="n">solve</span><span class="p">(</span><span class="n">k1</span><span class="p">,</span> <span class="n">eq</span> <span class="o">*</span> <span class="n">v2</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">v2</span> <span class="o">==</span> <span class="kc">None</span><span class="p">:</span>
        <span class="k">match</span> <span class="n">tree</span><span class="p">[</span><span class="n">key</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
            <span class="k">case</span> <span class="s1">'+'</span><span class="p">:</span> <span class="k">return</span> <span class="n">solve</span><span class="p">(</span><span class="n">k2</span><span class="p">,</span> <span class="n">eq</span> <span class="o">-</span> <span class="n">v1</span><span class="p">)</span>
            <span class="k">case</span> <span class="s1">'-'</span><span class="p">:</span> <span class="k">return</span> <span class="n">solve</span><span class="p">(</span><span class="n">k2</span><span class="p">,</span> <span class="n">v1</span> <span class="o">-</span> <span class="n">eq</span><span class="p">)</span>
            <span class="k">case</span> <span class="s1">'*'</span><span class="p">:</span> <span class="k">return</span> <span class="n">solve</span><span class="p">(</span><span class="n">k2</span><span class="p">,</span> <span class="n">eq</span> <span class="o">//</span> <span class="n">v1</span><span class="p">)</span>
            <span class="k">case</span> <span class="s1">'/'</span><span class="p">:</span> <span class="k">return</span> <span class="n">solve</span><span class="p">(</span><span class="n">k2</span><span class="p">,</span> <span class="n">v1</span> <span class="o">//</span> <span class="n">eq</span><span class="p">)</span>

<span class="n">tree</span><span class="p">[</span><span class="s1">'humn'</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
<span class="n">tree</span><span class="p">[</span><span class="s1">'root'</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="s1">'-'</span>

<span class="nb">print</span><span class="p">(</span><span class="n">solve</span><span class="p">(</span><span class="s1">'root'</span><span class="p">,</span> <span class="mi">0</span><span class="p">))</span>
</pre></div>

<h2>Day 22: Monkey Map</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/22">here</a>.</p>

<h3>Part 1</h3>

<p>This one was fun but a bit tedious. Part 1 is very easy, we implement movement with wrap-around and stopping when we hit <code>#</code>.</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>

<span class="n">grid</span> <span class="o">=</span> <span class="p">[</span><span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">150</span><span class="p">,</span> <span class="s1">' '</span><span class="p">)</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">()]</span>
<span class="n">dirs</span><span class="p">,</span> <span class="n">grid</span> <span class="o">=</span> <span class="p">[</span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">()</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="s1">'(\d+)|L|R'</span><span class="p">,</span> <span class="n">grid</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])],</span> <span class="n">grid</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span>
<span class="n">dirs</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="k">if</span> <span class="nb">str</span><span class="o">.</span><span class="n">isdecimal</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="k">else</span> <span class="n">d</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">dirs</span><span class="p">]</span>

<span class="n">facing</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)]</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="s1">'.'</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>

<span class="k">def</span><span class="w"> </span><span class="nf">move</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
    <span class="n">nx</span> <span class="o">=</span> <span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">d</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
    <span class="n">ny</span> <span class="o">=</span> <span class="p">(</span><span class="n">y</span> <span class="o">+</span> <span class="n">d</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="o">%</span> <span class="nb">len</span><span class="p">(</span><span class="n">grid</span><span class="p">)</span>
    <span class="k">match</span> <span class="n">grid</span><span class="p">[</span><span class="n">ny</span><span class="p">][</span><span class="n">nx</span><span class="p">]:</span>
        <span class="k">case</span> <span class="s1">' '</span><span class="p">:</span> 
            <span class="n">nx</span><span class="p">,</span> <span class="n">ny</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">nx</span><span class="p">,</span> <span class="n">ny</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
            <span class="k">return</span> <span class="p">(</span><span class="n">nx</span><span class="p">,</span> <span class="n">ny</span><span class="p">)</span> <span class="k">if</span> <span class="n">grid</span><span class="p">[</span><span class="n">ny</span><span class="p">][</span><span class="n">nx</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">' '</span> <span class="k">else</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
        <span class="k">case</span> <span class="s1">'#'</span><span class="p">:</span> <span class="k">return</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span>
        <span class="k">case</span> <span class="s1">'.'</span><span class="p">:</span> <span class="k">return</span> <span class="p">(</span><span class="n">nx</span><span class="p">,</span> <span class="n">ny</span><span class="p">)</span>

<span class="k">for</span> <span class="n">step</span> <span class="ow">in</span> <span class="n">dirs</span><span class="p">:</span>
    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">step</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
        <span class="k">while</span> <span class="n">step</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">facing</span><span class="p">[</span><span class="n">d</span><span class="p">])</span>
            <span class="n">step</span> <span class="o">-=</span> <span class="mi">1</span>
    <span class="k">elif</span> <span class="n">step</span> <span class="o">==</span> <span class="s1">'L'</span><span class="p">:</span>
        <span class="n">d</span> <span class="o">=</span> <span class="p">(</span><span class="n">d</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="mi">4</span> 
    <span class="k">else</span><span class="p">:</span>
        <span class="n">d</span> <span class="o">=</span> <span class="p">(</span><span class="n">d</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="mi">4</span>

<span class="nb">print</span><span class="p">(</span><span class="mi">1000</span> <span class="o">*</span> <span class="p">(</span><span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">d</span><span class="p">)</span>
</pre></div>

<h3>Part 2</h3>

<p>For part 2, we need to figure out how the various facets connect into a cube and
map movement from one face to another. Personally, I made a paper cutout of the
input shape, folded it, and used that to figure out the transitions:</p>

<p><img src="https://vladris.com/blog/2023/01/07/cube.jpeg" alt="Paper cube"/></p>

<p>The algorithm is pretty easy if the mappings are right. While on the same facet,
we simply move in the direction we are supposed to move. We can encode a facet
as a pair of <code>(region_x, region_y)</code> coordinates where <code>region_x, region_y = x //
50, y // 50</code>. Of course, some pairs of coordinates are not part of any facet of
the cube (e.g. <code>(0, 0)</code>) but that doesn't matter. Using this encoding, we can
tell when a movement gets us outside the current region. When that happens, we
have a helper function which helps figure out where we end up and what is the
new orientation.</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>

<span class="n">grid</span> <span class="o">=</span> <span class="p">[</span><span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span><span class="o">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">150</span><span class="p">,</span> <span class="s1">' '</span><span class="p">)</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">()]</span>
<span class="n">dirs</span><span class="p">,</span> <span class="n">grid</span> <span class="o">=</span> <span class="p">[</span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">()</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="s1">'(\d+)|L|R'</span><span class="p">,</span> <span class="n">grid</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">])],</span> <span class="n">grid</span><span class="p">[:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span>
<span class="n">dirs</span> <span class="o">=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="k">if</span> <span class="nb">str</span><span class="o">.</span><span class="n">isdecimal</span><span class="p">(</span><span class="n">d</span><span class="p">)</span> <span class="k">else</span> <span class="n">d</span> <span class="k">for</span> <span class="n">d</span> <span class="ow">in</span> <span class="n">dirs</span><span class="p">]</span>

<span class="n">size</span> <span class="o">=</span> <span class="mi">50</span>
<span class="n">facing</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)]</span>

<span class="n">connections</span> <span class="o">=</span> <span class="p">{</span>
    <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="p">[(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)],</span>
    <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">)],</span>
    <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">):</span> <span class="p">[(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">)],</span>
    <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">)],</span>
    <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">):</span> <span class="p">[(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">)],</span>
    <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">):</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)],</span>
<span class="p">}</span>

<span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="n">grid</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="s1">'.'</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>

<span class="k">def</span><span class="w"> </span><span class="nf">move</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
    <span class="n">nx</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">facing</span><span class="p">[</span><span class="n">d</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
    <span class="n">ny</span> <span class="o">=</span> <span class="n">y</span> <span class="o">+</span> <span class="n">facing</span><span class="p">[</span><span class="n">d</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
    <span class="n">nd</span> <span class="o">=</span> <span class="n">d</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">x</span> <span class="o">//</span> <span class="n">size</span><span class="p">,</span> <span class="n">y</span> <span class="o">//</span> <span class="n">size</span><span class="p">)</span> <span class="o">!=</span> <span class="p">(</span><span class="n">nx</span> <span class="o">//</span> <span class="n">size</span><span class="p">,</span> <span class="n">ny</span> <span class="o">//</span> <span class="n">size</span><span class="p">):</span>
        <span class="n">nx</span><span class="p">,</span> <span class="n">ny</span><span class="p">,</span> <span class="n">nd</span> <span class="o">=</span> <span class="n">switch_region</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>

    <span class="k">match</span> <span class="n">grid</span><span class="p">[</span><span class="n">ny</span><span class="p">][</span><span class="n">nx</span><span class="p">]:</span>
        <span class="k">case</span> <span class="s1">'#'</span><span class="p">:</span> <span class="k">return</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
        <span class="k">case</span> <span class="s1">'.'</span><span class="p">:</span> <span class="k">return</span> <span class="p">(</span><span class="n">nx</span><span class="p">,</span> <span class="n">ny</span><span class="p">,</span> <span class="n">nd</span><span class="p">)</span>

<span class="k">def</span><span class="w"> </span><span class="nf">switch_region</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">):</span>
    <span class="n">nrx</span><span class="p">,</span> <span class="n">nry</span><span class="p">,</span> <span class="n">nd</span> <span class="o">=</span> <span class="n">connections</span><span class="p">[(</span><span class="n">x</span> <span class="o">//</span> <span class="n">size</span><span class="p">,</span> <span class="n">y</span> <span class="o">//</span> <span class="n">size</span><span class="p">)][</span><span class="n">d</span><span class="p">]</span>
    <span class="n">nx</span><span class="p">,</span> <span class="n">ny</span> <span class="o">=</span> <span class="n">nrx</span> <span class="o">*</span> <span class="n">size</span><span class="p">,</span> <span class="n">nry</span> <span class="o">*</span> <span class="n">size</span>
    <span class="n">rx</span><span class="p">,</span> <span class="n">ry</span> <span class="o">=</span> <span class="n">x</span> <span class="o">%</span> <span class="n">size</span><span class="p">,</span> <span class="n">y</span> <span class="o">%</span> <span class="n">size</span>

    <span class="k">if</span> <span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">nd</span><span class="p">)</span> <span class="ow">in</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]:</span>
        <span class="k">return</span> <span class="n">nx</span> <span class="o">+</span> <span class="n">size</span> <span class="o">-</span> <span class="n">rx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">ny</span> <span class="o">+</span> <span class="n">ry</span><span class="p">,</span> <span class="n">nd</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">nd</span><span class="p">)</span> <span class="ow">in</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">3</span><span class="p">)]:</span>
        <span class="k">return</span> <span class="n">nx</span> <span class="o">+</span> <span class="n">rx</span><span class="p">,</span> <span class="n">ny</span> <span class="o">+</span> <span class="n">size</span> <span class="o">-</span> <span class="n">ry</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nd</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">nd</span><span class="p">)</span> <span class="ow">in</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">)]:</span>
        <span class="k">return</span> <span class="n">nx</span> <span class="o">+</span> <span class="n">size</span> <span class="o">-</span> <span class="n">ry</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">ny</span> <span class="o">+</span> <span class="n">size</span> <span class="o">-</span> <span class="n">rx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">nd</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">nd</span><span class="p">)</span> <span class="ow">in</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">)]:</span>
        <span class="k">return</span> <span class="n">nx</span> <span class="o">+</span> <span class="n">ry</span><span class="p">,</span> <span class="n">ny</span> <span class="o">+</span> <span class="n">rx</span><span class="p">,</span> <span class="n">nd</span>

<span class="k">for</span> <span class="n">step</span> <span class="ow">in</span> <span class="n">dirs</span><span class="p">:</span>
    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">step</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
        <span class="k">while</span> <span class="n">step</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="n">move</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
            <span class="n">step</span> <span class="o">-=</span> <span class="mi">1</span>
    <span class="k">elif</span> <span class="n">step</span> <span class="o">==</span> <span class="s1">'L'</span><span class="p">:</span>
        <span class="n">d</span> <span class="o">=</span> <span class="p">(</span><span class="n">d</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="mi">4</span> 
    <span class="k">else</span><span class="p">:</span>
        <span class="n">d</span> <span class="o">=</span> <span class="p">(</span><span class="n">d</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="mi">4</span>

<span class="nb">print</span><span class="p">(</span><span class="mi">1000</span> <span class="o">*</span> <span class="p">(</span><span class="n">y</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">4</span> <span class="o">*</span> <span class="p">(</span><span class="n">x</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">d</span><span class="p">)</span>
</pre></div>

<h2>Day 23: Unstable Diffusion</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/23">here</a>.</p>

<p>This is a cellular automaton. In general, when implementing cellular automata,
the <q>trick</q> is to not change things in place, rather use a new copy for each
generation. I represented the elves as a set of <code>(x, y)</code> coordinates. We can use
set intersection to see if an elf has other elves nearby or whether two elves
would end up moving in the same spot. I won't go into more detail as this was
another pretty easy problem. The code is on my GitHub.</p>

<h2>Day 24: Blizzard Basin</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/24">here</a>.</p>

<h3>Part 1</h3>

<p>I liked this one. For both part 1 and part 2, this becomes easy to solve with a
couple of interesting observations.</p>

<p>First the blizzards move in a repeating pattern so we can map which squares are
occupied at a given point in time and we know the occupancy repeats every
<code>lcm(height, width)</code> where <code>height</code> and <code>width</code> are the height and width of the
valley. We can compute this many generations and store the occupancy map in a
lookup.</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">math</span>

<span class="n">blizzards</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">lines</span> <span class="o">=</span> <span class="p">[</span><span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">()]</span>
<span class="k">for</span> <span class="n">y</span><span class="p">,</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">lines</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">c</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">c</span> <span class="ow">in</span> <span class="s1">'&lt;^&gt;v'</span><span class="p">:</span>
            <span class="n">blizzards</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">c</span><span class="p">))</span>

<span class="n">maxx</span><span class="p">,</span> <span class="n">maxy</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">lines</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
<span class="n">move</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'&lt;'</span><span class="p">:</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="s1">'^'</span><span class="p">:</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">),</span> <span class="s1">'&gt;'</span><span class="p">:</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="s1">'v'</span><span class="p">:</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)}</span>

<span class="k">def</span><span class="w"> </span><span class="nf">step</span><span class="p">(</span><span class="n">blizzards</span><span class="p">):</span>
    <span class="n">new</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="k">for</span> <span class="n">b</span> <span class="ow">in</span> <span class="n">blizzards</span><span class="p">:</span>
        <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="o">=</span> <span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">move</span><span class="p">[</span><span class="n">b</span><span class="p">[</span><span class="mi">2</span><span class="p">]][</span><span class="mi">0</span><span class="p">],</span> <span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">move</span><span class="p">[</span><span class="n">b</span><span class="p">[</span><span class="mi">2</span><span class="p">]][</span><span class="mi">1</span><span class="p">]</span>
        <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="n">x</span> <span class="o">=</span> <span class="n">maxx</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="n">x</span> <span class="o">==</span> <span class="n">maxx</span><span class="p">:</span> <span class="n">x</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="n">y</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span> <span class="n">y</span> <span class="o">=</span> <span class="n">maxy</span> <span class="o">-</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="n">y</span> <span class="o">==</span> <span class="n">maxy</span><span class="p">:</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">1</span>
        <span class="n">new</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">b</span><span class="p">[</span><span class="mi">2</span><span class="p">]))</span>
    <span class="k">return</span> <span class="n">new</span>

<span class="k">def</span><span class="w"> </span><span class="nf">occupancy</span><span class="p">(</span><span class="n">blizzards</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">{(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">blizzards</span><span class="p">}</span>

<span class="n">steps</span><span class="p">,</span> <span class="n">lcm</span> <span class="o">=</span> <span class="p">{},</span> <span class="n">math</span><span class="o">.</span><span class="n">lcm</span><span class="p">(</span><span class="n">maxx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">maxy</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">lcm</span><span class="p">):</span>
    <span class="n">steps</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">{(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">blizzards</span><span class="p">}</span>
    <span class="n">blizzards</span> <span class="o">=</span> <span class="n">step</span><span class="p">(</span><span class="n">blizzards</span><span class="p">)</span>
</pre></div>

<p>Next, we can do a breadth-first search to find the closest path from one side to
the other. Since a possible move is waiting one, its pretty hard to find bounds
for a depth-first search. On the other hand, at every step the elves can occupy
one of the at most <code>height * width</code> positions. Of course, most of these will be
occupied by blizzards. So for a BFS, we start from the initial position and time
(step <code>0</code>) and use a queue. We pop the first move and enqueue all possible moves
from this position (taking into account valley bounds and blizzard occupancy)
for the next step. As long as we ensure not to enqueue duplicates, the queue
stays small. Since this is BFS, as soon as the position we dequeue is our
destination, we know this is the earliest we can get there.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">solve</span><span class="p">():</span>
    <span class="n">queue</span> <span class="o">=</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)]</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">step</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        
        <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="p">[(</span><span class="n">x</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">y</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">move</span><span class="o">.</span><span class="n">values</span><span class="p">()]</span> <span class="o">+</span> <span class="p">[(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]:</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="n">maxx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">maxy</span><span class="p">):</span>
                <span class="k">return</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="o">!=</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">):</span>
                <span class="k">if</span> <span class="n">x</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">x</span> <span class="o">&gt;=</span> <span class="n">maxx</span> <span class="ow">or</span> <span class="n">y</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">y</span> <span class="o">&gt;=</span> <span class="n">maxy</span><span class="p">:</span>
                    <span class="k">continue</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="ow">in</span> <span class="n">steps</span><span class="p">[(</span><span class="n">step</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">lcm</span><span class="p">]:</span>
                <span class="k">continue</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">queue</span><span class="p">:</span>
                <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>

<span class="nb">print</span><span class="p">(</span><span class="n">solve</span><span class="p">())</span>
</pre></div>

<h3>Part 2</h3>

<p>The extra trips are no problem since this is very fast. The only changes I had
to make from part 1 to part 2 were modifying <code>solve()</code> to parameterize start,
destination, and initial point in time, then call it 3 times for each trip:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">solve</span><span class="p">(</span><span class="n">src</span><span class="p">,</span> <span class="n">dest</span><span class="p">,</span> <span class="n">step</span><span class="p">):</span>
    <span class="n">queue</span> <span class="o">=</span> <span class="p">[(</span><span class="n">src</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">src</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">step</span><span class="p">)]</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">step</span> <span class="o">=</span> <span class="n">queue</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
        
        <span class="k">for</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="ow">in</span> <span class="p">[(</span><span class="n">x</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">y</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">move</span><span class="o">.</span><span class="n">values</span><span class="p">()]</span> <span class="o">+</span> <span class="p">[(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)]:</span>
            <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="o">==</span> <span class="p">(</span><span class="n">dest</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">dest</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="k">return</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="o">!=</span> <span class="p">(</span><span class="n">src</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">src</span><span class="p">[</span><span class="mi">1</span><span class="p">]):</span>
                <span class="k">if</span> <span class="n">x</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">x</span> <span class="o">&gt;=</span> <span class="n">maxx</span> <span class="ow">or</span> <span class="n">y</span> <span class="o">&lt;=</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">y</span> <span class="o">&gt;=</span> <span class="n">maxy</span><span class="p">:</span>
                    <span class="k">continue</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">)</span> <span class="ow">in</span> <span class="n">steps</span><span class="p">[(</span><span class="n">step</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">lcm</span><span class="p">]:</span>
                <span class="k">continue</span>

            <span class="k">if</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">queue</span><span class="p">:</span>
                <span class="n">queue</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">step</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>

<span class="n">trip1</span> <span class="o">=</span> <span class="n">solve</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="n">maxx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">maxy</span><span class="p">),</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">trip2</span> <span class="o">=</span> <span class="n">solve</span><span class="p">((</span><span class="n">maxx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">maxy</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">trip1</span><span class="p">)</span>
<span class="n">trip3</span> <span class="o">=</span> <span class="n">solve</span><span class="p">((</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="p">(</span><span class="n">maxx</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">maxy</span><span class="p">),</span> <span class="n">trip2</span><span class="p">)</span>
<span class="nb">print</span><span class="p">(</span><span class="n">trip3</span><span class="p">)</span>
</pre></div>

<h2>Day 25: Full of Hot Air</h2>

<p>Problem statement is <a href="https://adventofcode.com/2022/day/25">here</a>.</p>

<p>Another easy one that I won't discuss in detail, we just need to implement
conversion from decimal to SNAFU and back:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">to_dec</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">digits</span> <span class="o">=</span> <span class="p">{</span><span class="s1">'0'</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">'1'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'2'</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">:</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'='</span><span class="p">:</span> <span class="o">-</span><span class="mi">2</span><span class="p">}</span>
    <span class="k">return</span> <span class="nb">sum</span><span class="p">([</span><span class="mi">5</span> <span class="o">**</span> <span class="n">i</span> <span class="o">*</span> <span class="n">digits</span><span class="p">[</span><span class="n">d</span><span class="p">]</span> <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">d</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">n</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">])])</span>

<span class="k">def</span><span class="w"> </span><span class="nf">to_snafu</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="n">s</span> <span class="o">=</span> <span class="s1">''</span>
    <span class="k">while</span> <span class="n">n</span><span class="p">:</span>
        <span class="n">s</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'0'</span><span class="p">,</span> <span class="s1">'1'</span><span class="p">,</span> <span class="s1">'2'</span><span class="p">,</span> <span class="s1">'='</span><span class="p">,</span> <span class="s1">'-'</span><span class="p">][</span><span class="n">n</span> <span class="o">%</span> <span class="mi">5</span><span class="p">]</span> <span class="o">+</span> <span class="n">s</span>
        <span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">//</span> <span class="mi">5</span> <span class="o">+</span> <span class="p">(</span><span class="mi">1</span> <span class="k">if</span> <span class="n">s</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="s1">'-='</span> <span class="k">else</span> <span class="mi">0</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">s</span>

<span class="nb">print</span><span class="p">(</span><span class="n">to_snafu</span><span class="p">(</span><span class="nb">sum</span><span class="p">([</span><span class="n">to_dec</span><span class="p">(</span><span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">open</span><span class="p">(</span><span class="s1">'input'</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">()])))</span>
</pre></div>

<p>In Advent of Code tradition, day 25 has only 1 part.</p>

<p>This was another very fun set of problems and I am looking forward to Advent of
Code 2023.</p>
]]></description>
      <pubDate>Sat, 07 Jan 2023 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/12/01/computability-part-9-lisp.html</link>
      <guid>https://vladris.com/blog/2022/12/01/computability-part-9-lisp.html</guid>
      <title><![CDATA[Computability Part 9: LISP]]></title>
      <description><![CDATA[<h1>Computability Part 9: LISP</h1>

<p>In the <a href="https://vladris.com/blog/2022/10/14/computability-part-8-lambda-calculus.html">previous post</a>,
we covered lambda calculus, a computational model underpinning <em>functional
programming</em>. In this blog post, we'll continue down the functional programming
road and cover one of the oldest programming languages still in use: LISP.</p>

<p>LISP was originally specified in 1958 by John McCarthy and the paper describing
the language was published in 1960<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. It became very popular in AI research
and flavors of it are still in use today.</p>

<p>LISP has a quite unique syntax and execution model.</p>

<h2>S-expression</h2>

<p>If we are going to talk about LISP, we need to start with <em>symbolic
expressions</em>. Symbolic expressions, or S-expressions, are defined as:</p>

<p>An S-expression is either</p>

<ol>
<li>an atom, or</li>
<li>an expression of the form <code>(x . y)</code></li>
</ol>

<p>where <code>x</code> and <code>y</code> are S-expressions.</p>

<p>This very simple definition is very powerful: it allows us to represent any
binary tree. Let's start with a very simple universe where the only atom is
<code>()</code>, representing a null value. With this atom and the above definition, while
we can't (easily) represent data, we can capture the shape of a binary tree. For
example, the tree consisting of a root node and two leaf nodes:</p>

<p><img src="./fig1.svg" alt="Binary tree shape"/></p>

<p>can be represented as <code>(() . ())</code>.</p>

<p>The tree consisting of a root, a left leaf node, and a right node with two child
leaf nodes</p>

<p><img src="./fig2.svg" alt="Binary tree"/></p>

<p>would be <code>(() . (() . ()))</code>.</p>

<p>If we expand the definition of atom to include numbers and basic arithmetic
(<code>+</code>, <code>-</code>, <code>*</code>, <code>/</code>), we can represent arithmetic expressions as S-expressions.
<code>2 + 3</code></p>

<p><img src="./fig3.svg" alt="2 + 3"/></p>

<p>can be represented as <code>(+ . (2 . (3 . ()))</code>.</p>

<p><code>2 * (3 + 5)</code></p>

<p><img src="./fig4.svg" alt="2 * (3 + 5)"/></p>

<p>can be represented as <code>(* . (2 . ((+ . (3 . (5 . ()))) . ())</code>.</p>

<p>Note the S-expression definition only allows for <q>values</q> (atoms) at leaf nodes
of the tree. An S-expression is either a leaf node containing a value or a
non-leaf node with 2 S-expression children. That means we can't represent <code>2 +
3</code> as</p>

<p><img src="./fig5.svg" alt="2 + 3"/></p>

<p>but the representation we just saw is equivalent.</p>

<h3>Representing data</h3>

<p>S-expressions can be used to represent data. Consider a simple list <code>1, 2, 3, 4,
5</code>. Much like we saw in the previous post when we looked at representing lists
as lambda expressions, we can represent lists using S-expressions using a head
and a tail (recursively):</p>

<p><img src="./fig6.svg" alt="List"/></p>

<p>can be viewed as</p>

<p><img src="./fig7.svg" alt="Tree list"/></p>

<p>or <code>(1 . (2 . (3 . (4 . (5 . ())))))</code>.</p>

<p>We can also represent an associative array: instead of a value, we can represent
a key-value pair as an S-expression (<code>(key . value)</code>), so we can represent the
associative array <code>{ 1: 2, 2: 3, 3: 5 }</code> as <code>((1 . 2) . ((2 . 3) . ((3 . 5) .
())))</code>.</p>

<p>Historically, a non-atom S-expression in LISP is called a <em>cons cell</em> (from
<q>construction</q>). Instead of <em>head</em> and <em>tail</em>, LISP uses <em>car</em> and <em>cdr</em>
(standing for <em>contents of the address register</em> and <em>contents of the decrement
register</em>, which are artifacts of the computer architecture first flavors of
LISP were implemented in).</p>

<p>We just saw how we can represent trees, lists, and associative arrays using
S-expressions. But S-expressions aren't limited to representing data: we can
also use them to represent code.</p>

<h3>Representing code</h3>

<p>We looked at how <code>2 + 3</code> would look like as an S-expression. In fact, we can
represent any function call as an S-expression, where the left node of the root
S-expression is the function to be called and the right subtree contains the
arguments.</p>

<p><code>2 + 3</code> is equivalent to the function <code>add(2, 3)</code>. So we can represent the
function call <code>add(2, 3)</code> as the S-expression <code>(add . (2 . (3 . ())))</code>.</p>

<p>Note we can have any number of arguments as we grow the right subtrees: <code>sum(2,
3, 4, 5)</code> can be represented as <code>(sum . (2 . (3 . (4 . (5 . ())))))</code>. If we want
to pass the result of another function as an argument, say <code>sum(2, sum(3, 4),
5)</code>, we can represent this as <code>(sum . (2 . ((sum . (3 . (4 . ()))) . (5 . ()))
))</code>.</p>

<p>We saw in the previous post that we can represent pretty much anything using
functions. An if expression is a function <code>if(condition, true-branch,
false-branch)</code>. We can combine this with recursion to generate loops. So we have
all the building blocks for a Turing-complete system.</p>

<p>It turns out we can represent both data and code as S-expressions. Before
moving on to look at some implementation details, let's introduce some syntactic
sugar.</p>

<h3>Syntactic sugar</h3>

<p>Writing S-expression like this can become tedious, so let's introduce some
syntactic sugar.  Instead of <code>(1 . (2 . (3 . (4 . (5 . ())))))</code>, we can write
<code>(1 2 3 4 5)</code>. We omit some of the parenthesis, the concatenation symbol <code>.</code>,
and the final <code>()</code>. By default, we concatenate on the right subtree. If we need
to go down the left subtree, we add parenthesis. So instead of representing the
associative array <code>{ 1: 2, 2: 3, 3: 5 }</code> as <code>((1 . 2) . ((2 . 3) . ((3 . 5) .
())))</code>, we can more succinctly represent it as <code>((1 2) (2 3) (3 5))</code>, without
losing any meaning.</p>

<p>Similarly, <code>(add . (2 . (3 . ())))</code> becomes <code>(add 2 3)</code> and <code>(sum . (2 . ((sum .
(3 . (4 . ()))) . (5 . ()))))</code> becomes <code>(sum 2 (sum 3 4) 5)</code>.</p>

<p>In our implementation, we will represent S-expressions as lists which can
contain any number of elements. This is a more succinct representation and will
make our code easier to understand.</p>

<h2>Implementation</h2>

<p>We can now look at implementing a small LISP. We take an input string, we parse
it into an S-expression, then we evaluate the S-expression and print the result.</p>

<p>First, the parser: we will take a string as input, split it into tokens, then
parse the tokens into an S-expression.</p>

<p>We will transform an input string into a list of tokens by matching it with
either <code>(</code>, <code>)</code>, or a string of alphanumeric characters. We'll use a regular
expression for this, then extract the matched values (using <code>match.group()</code>)
into a list:</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">re</span>

<span class="k">def</span><span class="w"> </span><span class="nf">lex</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">[</span><span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">()</span> <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="s1">'\(|\)|\w+'</span><span class="p">,</span> <span class="n">line</span><span class="p">)]</span>
</pre></div>

<p>We can now transform an input like <code>'(add 1 (add 2 3))'</code> into the list of tokens
<code>['(', 'add', '1', '(', 'add', '2', '3', ')', ')']</code> by calling <code>lex()</code> on it.</p>

<p>We need to transform this list of tokens into an S-expression. First, we need a
couple of helper functions. An atom can be either a number or a symbol. We'll
create one from a token using an <code>atom()</code> function:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">atom</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
    <span class="k">except</span><span class="p">:</span>
        <span class="k">return</span> <span class="n">value</span>
</pre></div>

<p>The other helper function will yield while the head of our token list is
different than <code>)</code>, then pop the <code>)</code> token. We'll use this while parsing to
iterate over the tokens after a <code>(</code> and until we find the matching <code>)</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">pop_rpar</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
    <span class="k">while</span> <span class="n">tokens</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">')'</span><span class="p">:</span>
        <span class="k">yield</span>
    <span class="n">tokens</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</pre></div>

<p>Parsing into an S-expression is now very simple:</p>

<ul>
<li>If we find a <code>(</code>, we recursively parse the following tokens until we reach
the matching <code>)</code>.</li>
<li>If we find a <code>)</code>, we raise an exception - this is an unmatched <code>)</code>.</li>
<li>Otherwise we have an atom - we return the result of calling <code>atom()</code> on it.</li>
</ul>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">parse</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
    <span class="k">match</span> <span class="n">token</span> <span class="o">:=</span> <span class="n">tokens</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">):</span>
        <span class="k">case</span> <span class="s1">'('</span><span class="p">:</span>
            <span class="k">return</span> <span class="p">[</span><span class="n">parse</span><span class="p">(</span><span class="n">tokens</span><span class="p">)</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">pop_rpar</span><span class="p">(</span><span class="n">tokens</span><span class="p">)]</span>
        <span class="k">case</span> <span class="s1">')'</span><span class="p">:</span>
            <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s1">'Unexpected )'</span><span class="p">)</span>
        <span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">atom</span><span class="p">(</span><span class="n">token</span><span class="p">)</span>
</pre></div>

<p>That's it. If we parse the input string <code>'(add 1 (add 2 3))'</code> using our
functions - <code>parse(lex('(add 1 (add 2 3))'))</code> - we will get back
<code>['add', 1, ['add', 2, 3]]</code>.</p>

<p>We can now take text as input and convert it into the internal representation
we discussed.</p>

<p>The next step is to evaluate such an S-expression and return a result. We need
two pieces for this: an environment which stores built-in functions and
user-defined variables, and an evaluation function which takes an S-expression
and processes it using the environment.</p>

<p>We'll start with a simple environment with built-in support for equality,
arithmetic operations and list operations:</p>
<div class="highlight"><pre><span/><span class="n">env</span> <span class="o">=</span> <span class="p">{</span>
    <span class="c1"># Equality</span>
    <span class="s1">'eq'</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">:</span> <span class="n">arg1</span> <span class="o">==</span> <span class="n">arg2</span><span class="p">,</span>

    <span class="c1"># Arithmetic</span>
    <span class="s1">'add'</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">:</span> <span class="n">arg1</span> <span class="o">+</span> <span class="n">arg2</span><span class="p">,</span>
    <span class="s1">'sub'</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">:</span> <span class="n">arg1</span> <span class="o">-</span> <span class="n">arg2</span><span class="p">,</span>
    <span class="s1">'mul'</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">:</span> <span class="n">arg1</span> <span class="o">*</span> <span class="n">arg2</span><span class="p">,</span>
    <span class="s1">'div'</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">:</span> <span class="n">arg1</span> <span class="o">/</span> <span class="n">arg2</span><span class="p">,</span>

    <span class="c1"># Lists</span>
    <span class="s1">'cons'</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">car</span><span class="p">,</span> <span class="n">cdr</span><span class="p">:</span> <span class="p">[</span><span class="n">car</span><span class="p">]</span> <span class="o">+</span> <span class="n">cdr</span><span class="p">,</span>
    <span class="s1">'car'</span><span class="p">:</span> <span class="k">lambda</span> <span class="nb">list</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
    <span class="s1">'cdr'</span><span class="p">:</span> <span class="k">lambda</span> <span class="nb">list</span><span class="p">:</span> <span class="nb">list</span><span class="p">[</span><span class="mi">1</span><span class="p">:],</span>
<span class="p">}</span>
</pre></div>

<p>Our evaluation function has a few special-case handling for variable
definitions, quotations, and if-expressions, and is otherwise pretty
straightforward:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">):</span>
    <span class="c1"># If null or number atom, return it</span>
    <span class="k">if</span> <span class="n">sexpr</span> <span class="o">==</span> <span class="p">[]</span> <span class="ow">or</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">sexpr</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">sexpr</span>

    <span class="c1"># If string atom, look it up in environment</span>
    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">sexpr</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">env</span><span class="p">[</span><span class="n">sexpr</span><span class="p">]</span>

    <span class="k">match</span> <span class="n">sexpr</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
        <span class="k">case</span> <span class="s1">'def'</span><span class="p">:</span>
            <span class="n">env</span><span class="p">[</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
        <span class="k">case</span> <span class="s1">'quote'</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="k">case</span> <span class="s1">'if'</span><span class="p">:</span>
            <span class="k">return</span> <span class="nb">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="k">if</span> <span class="nb">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="k">else</span> <span class="nb">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>
        <span class="k">case</span> <span class="n">call</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">env</span><span class="p">[</span><span class="n">call</span><span class="p">](</span><span class="o">*</span><span class="p">[</span><span class="nb">eval</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">:]])</span>
</pre></div>

<p>Our evaluation works like this:</p>

<ul>
<li>If we have an atom representing the empty list, we return it.</li>
<li>If we have an atom that is a number, we'll return its value.</li>
<li>If we have an atom that is a string (a symbol), we'll look it up in the
environment and return what we find there.</li>
<li>Otherwise we don't have an atom, rather an S-expression.

<ul>
<li>If the first symbol is <code>def</code>, we add a definition to the environment.</li>
<li>If the first symbol is <code>quote</code>, we return the second symbol unevaluated.</li>
<li>If the first symbol is <code>if</code>, we evaluate the second symbol and if it is
truthy, we evaluate the third symbol, otherwise the fourth symbol.</li>
<li>If the first symbol doesn't denote a definition or an if expression, it
is a function call: we grab the function from the environment,
recursively evaluate all arguments, and pass them to the function.</li>
</ul></li>
</ul>

<p>We're taking a bit of a shortcut here and relying on Python's notion of
truthy-ness (e.g. <code>0</code> or an empty list <code>[]</code> is non-truthy). If needed, we can
enhance our implementation with Boolean support.</p>

<p>We can now implement a simple read-eval-print loop (REPL):</p>
<div class="highlight"><pre><span/><span class="k">while</span> <span class="n">line</span> <span class="o">:=</span> <span class="nb">input</span><span class="p">(</span><span class="s1">'&gt; '</span><span class="p">):</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="nb">print</span><span class="p">(</span><span class="nb">eval</span><span class="p">(</span><span class="n">parse</span><span class="p">(</span><span class="n">lex</span><span class="p">(</span><span class="n">line</span><span class="p">))))</span>
    <span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="nb">type</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s1">: </span><span class="si">{</span><span class="n">e</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
</pre></div>

<p>We can try a few simple commands (shown below with the corresponding output):</p>
<div class="highlight"><pre><span/><span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">def</span><span class="w"> </span><span class="nv">a</span><span class="w"> </span><span class="mi">40</span><span class="p">)</span>
<span class="nv">None</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">def</span><span class="w"> </span><span class="nv">b</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span>
<span class="nv">None</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">add</span><span class="w"> </span><span class="nv">a</span><span class="w"> </span><span class="nv">b</span><span class="p">)</span>
<span class="mi">42</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="nv">a</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="mi">1</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">add</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="p">(</span><span class="nv">add</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="mi">4</span><span class="p">))</span>
<span class="mi">9</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">def</span><span class="w"> </span><span class="nb">list</span><span class="w"> </span><span class="p">(</span><span class="nb">cons</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">(</span><span class="nb">cons</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="p">(</span><span class="nb">cons</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">()))))</span>
<span class="nv">None</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nb">car</span><span class="w"> </span><span class="nb">list</span><span class="p">)</span>
<span class="mi">1</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nb">cdr</span><span class="w"> </span><span class="nb">list</span><span class="p">)</span>
<span class="nv">[2,</span><span class="w"> </span><span class="nv">3]</span>
</pre></div>

<h3>Custom functions</h3>

<p>We can extend the environment with additional functions as needed. These
represent the <q>built-in</q> functions of our LISP interpreter. One capability we
are still missing is the ability to define custom functions at runtime. Let's
extend our interpreter to support that.</p>

<p>A function can take any number of arguments, which should become defined in
the environment while the function is executing but which don't exist outside
the function. For example, if we define an addition function as <code>add(x, y)</code>,
we should be able to refer to the <code>x</code> and <code>y</code> arguments inside the body of the
function but not outside of it. <code>x</code> and <code>y</code> only exist within the <em>scope</em> of
the function.</p>

<p>We can add scoping to our interpreter by extending our <code>eval</code> to take an
environment as an argument instead of always referencing our <code>env</code>. Then when
we create a new scope, we create a new environment to use.</p>

<p>For function definition, we will use the following syntax: <code>(deffun
function_name (arguments...) (body...))</code>. <code>deffun</code> denotes a function
definition. The second argument is the function name. The third is a list of
parameters and the fourth is the body of the function, which is going to be
evaluated in an environment where its arguments are defined.</p>

<p>We need a function factory:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">make_function</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">body</span><span class="p">,</span> <span class="n">env</span><span class="p">):</span>
    <span class="k">return</span> <span class="k">lambda</span> <span class="o">*</span><span class="n">args</span><span class="p">:</span> <span class="nb">eval</span><span class="p">(</span><span class="n">body</span><span class="p">,</span> <span class="n">env</span> <span class="o">|</span> <span class="nb">dict</span><span class="p">(</span><span class="nb">zip</span><span class="p">(</span><span class="n">params</span><span class="p">,</span> <span class="n">args</span><span class="p">)))</span>
</pre></div>

<p>This takes the parameters, body, and environment and returns a lambda which
expects a list of arguments. Calling the lambda will invoke <code>eval</code> on the
body. Note we extend the environment with a dictionary mapping parameters to
arguments.</p>

<p>Let's update <code>eval</code> to use a parameterized environment and support the new
<code>deffun</code> function definition capability:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">,</span> <span class="n">env</span><span class="o">=</span><span class="n">env</span><span class="p">):</span>
    <span class="c1"># If number atom, return value</span>
    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">sexpr</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">sexpr</span>

    <span class="c1"># If string atom, look it up in environment</span>
    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">sexpr</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
        <span class="k">return</span> <span class="n">env</span><span class="p">[</span><span class="n">sexpr</span><span class="p">]</span>

    <span class="k">if</span> <span class="n">sexpr</span> <span class="o">==</span> <span class="p">[]:</span>
        <span class="k">return</span> <span class="p">[]</span>

    <span class="k">match</span> <span class="n">sexpr</span><span class="p">[</span><span class="mi">0</span><span class="p">]:</span>
        <span class="k">case</span> <span class="s1">'def'</span><span class="p">:</span>
            <span class="n">env</span><span class="p">[</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">env</span><span class="p">)</span>
        <span class="k">case</span> <span class="s1">'deffun'</span><span class="p">:</span>
            <span class="n">env</span><span class="p">[</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="n">make_function</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">sexpr</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">env</span><span class="p">)</span>
        <span class="k">case</span> <span class="s1">'quote'</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="k">case</span> <span class="s1">'if'</span><span class="p">:</span>
            <span class="k">return</span> <span class="nb">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">env</span><span class="p">)</span> <span class="k">if</span> <span class="nb">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">env</span><span class="p">)</span> <span class="k">else</span> <span class="nb">eval</span><span class="p">(</span><span class="n">sexpr</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span> <span class="n">env</span><span class="p">)</span>
        <span class="k">case</span> <span class="n">call</span><span class="p">:</span>
            <span class="k">return</span> <span class="n">env</span><span class="p">[</span><span class="n">call</span><span class="p">](</span><span class="o">*</span><span class="p">[</span><span class="nb">eval</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">env</span><span class="p">)</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">sexpr</span><span class="p">[</span><span class="mi">1</span><span class="p">:]])</span>
</pre></div>

<p>Besides plumbing <code>env</code> through each <code>eval</code> call, we just added a <code>deffun</code> case where
we use our function factory.</p>

<p>We can run our REPL again and try out the new capability:</p>
<div class="highlight"><pre><span/><span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">deffun</span><span class="w"> </span><span class="nv">myadd</span><span class="w"> </span><span class="p">(</span><span class="nv">x</span><span class="w"> </span><span class="nv">y</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nv">add</span><span class="w"> </span><span class="nv">x</span><span class="w"> </span><span class="nv">y</span><span class="p">))</span>
<span class="nv">None</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">myadd</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="mi">3</span><span class="p">)</span>
<span class="mi">5</span>
</pre></div>

<p>Here is a Fibonacci implementation, using <code>deffun</code> and recursion:</p>
<div class="highlight"><pre><span/><span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">deffun</span><span class="w"> </span><span class="nv">fib</span><span class="w"> </span><span class="p">(</span><span class="nv">n</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nb">eq</span><span class="w"> </span><span class="nv">n</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nb">eq</span><span class="w"> </span><span class="nv">n</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">(</span><span class="nv">add</span><span class="w"> </span><span class="p">(</span><span class="nv">fib</span><span class="w"> </span><span class="p">(</span><span class="nv">sub</span><span class="w"> </span><span class="nv">n</span><span class="w"> </span><span class="mi">1</span><span class="p">))</span><span class="w"> </span><span class="p">(</span><span class="nv">fib</span><span class="w"> </span><span class="p">(</span><span class="nv">sub</span><span class="w"> </span><span class="nv">n</span><span class="w"> </span><span class="mi">2</span><span class="p">))))))</span>
<span class="nv">None</span>
<span class="nb">&gt;</span><span class="w"> </span><span class="p">(</span><span class="nv">fib</span><span class="w"> </span><span class="mi">8</span><span class="p">)</span>
<span class="mi">21</span>
</pre></div>

<p>If <code>n</code> is 0, return <code>0</code> else if <code>n</code> is 1, return <code>1</code>, else recursively call
<code>fib</code> for <code>n - 1</code> and <code>n - 2</code> and add the results.</p>

<p>We won't provide a proof of Turing-completeness but it should be obvious that
the capabilities we implemented so far are sufficient to emulate, for example,
a cyclic tag system like we did in the previous post with lambdas.</p>

<h2>Conclusions</h2>

<p>The full implementation of our mini-LISP is <a href="https://vladris.com/code/LISP/lisp.py">here</a>.</p>

<p>Peter Norvig wrote a much more detailed article describing a LISP implementation
<a href="https://norvig.com/lispy.html">here</a>.</p>

<p>LISP is a very interesting language as it uses the same representation for both
data and code (for better or worse). Turns out binary trees (or trees if we use
our syntactic sugar) are enough to represent both.</p>

<p>As we just saw, a core LISP runtime is fairly easy to implement and many of the
more advanced features can be bootstrapped within the language itself.</p>

<p>Languages in the LISP family are called <em>LISP dialects</em>. Even though the
language is many decades old, modern dialects are alive and thriving. For
example Raket and Closure are LISP dialects.</p>

<h2>Summary</h2>

<p>In this post we looked at LISP:</p>

<ul>
<li>S-expressions which describe binary trees.</li>
<li>Representing data as S-expressions.</li>
<li>Representing code as S-expressions.</li>
<li>A simple LISP implementation including a lexer, parser, environment,
evaluation function, and a REPL.</li>
<li>Extending this with custom function definitions.</li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>Original paper: <a href="http://www-formal.stanford.edu/jmc/recursive.pdf">http://www-formal.stanford.edu/jmc/recursive.pdf</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Thu, 01 Dec 2022 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/10/14/computability-part-8-lambda-calculus.html</link>
      <guid>https://vladris.com/blog/2022/10/14/computability-part-8-lambda-calculus.html</guid>
      <title><![CDATA[Computability Part 8: Lambda Calculus]]></title>
      <description><![CDATA[<h1>Computability Part 8: Lambda Calculus</h1>

<p>In the previous posts, we dug deeper into one particular model of computation,
starting with Turing Machines in <a href="https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html">part 2</a>,
to the von Neumann computer architecture in <a href="https://vladris.com/blog/2022/07/31/computability-part-6-von-neumann-architecture.html">part 6</a>,
to some of the implementation practicalities of machines - physical or virtual
- in <a href="https://vladris.com/blog/2022/09/02/computability-part-7-machine-implementation-practicalities.html">part 7</a>.</p>

<p>We'll switch gears and cover another computational model this time around:
<em>lambda calculus</em>. Lambda calculus was developed by Alonzo Church around the
same time Alan Turing was proposing the Turing machine as a universal model for
computation. The <em>Church-Turing thesis</em><sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup> proves the equivalence between the
two models - anything a Turing machine can compute can also be computed by
lambda calculus.</p>

<p>Formally:</p>

<blockquote>
<p>Lambda calculus consists of lambda terms and reductions applied to lambda
terms.</p>

<p>The lambda terms are built with the following rules, where \(\Lambda\) is the
set of all possible lambda terms:</p>

<ul>
<li><em>Variables</em>, like \(x\), are lambda terms. \(x \in \Lambda\).</li>
<li><em>Abstractions</em>, \((\lambda x.M)\). This is a function definition where \(M\) is
a lambda term and \(x\) becomes <em>bound</em> in the expression. For \(x \in \Lambda\)
and \(M \in \Lambda\), \((\lambda x.M) \in \Lambda\). </li>
<li><em>Applications</em>, \((M \space N)\). This applies the function \(M\) to the
argument \(N\), where \(M\) and \(N\) are lambda terms. For \(M \in \Lambda\) and \(N
\in \Lambda\), \((M \space N) \in \Lambda\).</li>
</ul>

<p>If a term \(y\) appears in \(M\) but is not bound, then \(y\) is <em>free</em> in \(M\), e.g.
for \(\lambda x.y \space x\), \(x\) is bound and \(y\) is free.
The reductions are:</p>

<ul>
<li><em>\(\alpha\)-equivalence</em>: bound variables in an expression can be renamed to
avoid collisions: \((\lambda x.M[x]) \rightarrow (\lambda y.M[y])\).</li>
<li><em>\(\beta\)-reduction</em>: bound variables in the body of an abstraction are
replaced with the argument expression: \((\lambda x.t)s \rightarrow
t[x := s]\).</li>
<li><em>\(\eta\)-reduction</em>: if \(x\) is a variable that does not appear free in the
lambda term <em>M</em>, then \(\lambda x.(M x) \rightarrow M\). This can also be
understood in terms of function equivalence: if two functions give the same
result for all arguments, then the functions are equivalent.</li>
</ul>
</blockquote>

<p>Let's look at a few simple examples in Python:</p>
<div class="highlight"><pre><span/><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span>
</pre></div>

<p>This is the identity function expressed as a lambda abstraction. In this case,
<code>x</code> (the lambda parameter), becomes bound in the body of the lambda.</p>

<p>\(\alpha\)-equivalence:</p>
<div class="highlight"><pre><span/><span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="n">y</span>
</pre></div>

<p>This is the same identity function, we're just using <code>y</code> instead of <code>x</code> to name
the parameter.</p>

<p>For function application, we can apply the identity function to any other lambda
term and get back that lambda term:</p>
<div class="highlight"><pre><span/><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">)(</span><span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="n">y</span><span class="p">)</span>
</pre></div>

<p>This applied the identify function <code>lambda x: x</code> to the argument <code>lambda y: y</code>,
which will give us back <code>lambda y: y</code>.</p>

<h2>Church encoding</h2>

<p>Based on the above definition, lambda calculus consists <em>exclusively</em> of lambda
terms - while <code>(lambda x: x)(10)</code> is valid Python code, applying an identity
lambda to the number <code>10</code>, lambda calculus does not have a number <code>10</code>. Enter
<em>Church encoding</em>: Alonzo Church came up with a way to encode logic values and
numbers as lambda terms.</p>

<h3>Logic</h3>

<p>Let's start with Boolean logic: <code>TRUE</code> is defined as \(T := (\lambda x.\lambda
y.x)\), <code>FALSE</code> is defined as \(F := (\lambda x.\lambda y.y)\).</p>
<div class="highlight"><pre><span/><span class="n">TRUE</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="n">x</span>
<span class="n">FALSE</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="n">y</span>
</pre></div>

<p>Note with this definition, if we apply a first argument to <code>TRUE</code>, and a second
argument to the returned lambda, we always get back the first argument. For
<code>FALSE</code>, we always get back the second argument.</p>

<p>We can defined <code>IF</code> as \(IF := (\lambda x.x)\). This is the same as the identity
function.</p>
<div class="highlight"><pre><span/><span class="n">IF</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span>
</pre></div>

<p>This works since we defined <code>TRUE</code> to always return the first argument and
<code>FALSE</code> to always return the second argument. So when we call <code>IF(c)(x)(y)</code>,
if <code>c</code> is <code>TRUE</code>, we get back <code>x</code> (the if-branch), otherwise we get back <code>y</code>
(the else-branch).</p>

<p>We can try this out (though again this is outside of lambda calculus, we are
introducing numbers for clarity):</p>
<div class="highlight"><pre><span/><span class="n">IF</span><span class="p">(</span><span class="n">TRUE</span><span class="p">)(</span><span class="mi">1</span><span class="p">)(</span><span class="mi">2</span><span class="p">)</span>  <span class="c1"># This returns 1</span>
<span class="n">IF</span><span class="p">(</span><span class="n">FALSE</span><span class="p">)(</span><span class="mi">1</span><span class="p">)(</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># This returns 2</span>
</pre></div>

<p>Now that we can express if-then-else, we can easily express other logic
operators. Negation is \(\lambda x.(x \space F \space T)\).</p>
<div class="highlight"><pre><span/><span class="n">NOT</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span><span class="p">(</span><span class="n">FALSE</span><span class="p">)(</span><span class="n">TRUE</span><span class="p">)</span>
</pre></div>

<p>If <code>x</code> is <code>TRUE</code>, we get back the first argument, <code>FALSE</code>; if <code>x</code> is <code>FALSE</code>,
we get back the second argument, <code>TRUE</code>.</p>

<p><code>x AND y</code> can be expressed as <em>if x then y else FALSE</em>, or: \(\lambda x.\lambda
y.(x \space y \space F)\). <code>x OR y</code> can be expressed as <em>if x then TRUE else y</em>,
or \(\lambda x.\lambda y.(x \space T \space y)\).</p>
<div class="highlight"><pre><span/><span class="n">AND</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="n">x</span><span class="p">(</span><span class="n">y</span><span class="p">)(</span><span class="n">FALSE</span><span class="p">)</span>
<span class="n">OR</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="n">x</span><span class="p">(</span><span class="n">TRUE</span><span class="p">)(</span><span class="n">y</span><span class="p">)</span>
</pre></div>

<p>Here are a few examples:</p>
<div class="highlight"><pre><span/><span class="nb">print</span><span class="p">(</span><span class="n">AND</span><span class="p">(</span><span class="n">TRUE</span><span class="p">)(</span><span class="n">TRUE</span><span class="p">)</span> <span class="o">==</span> <span class="n">TRUE</span><span class="p">)</span>  <span class="c1"># prints True</span>
<span class="nb">print</span><span class="p">(</span><span class="n">AND</span><span class="p">(</span><span class="n">TRUE</span><span class="p">)(</span><span class="n">FALSE</span><span class="p">)</span> <span class="o">==</span> <span class="n">TRUE</span><span class="p">)</span> <span class="c1"># prints False</span>
<span class="nb">print</span><span class="p">(</span><span class="n">OR</span><span class="p">(</span><span class="n">TRUE</span><span class="p">)(</span><span class="n">FALSE</span><span class="p">)</span> <span class="o">==</span> <span class="n">TRUE</span><span class="p">)</span>  <span class="c1"># prints True</span>
<span class="nb">print</span><span class="p">(</span><span class="n">NOT</span><span class="p">(</span><span class="n">FALSE</span><span class="p">)</span> <span class="o">==</span> <span class="n">TRUE</span><span class="p">)</span>       <span class="c1"># prints True</span>
</pre></div>

<p>Using only lambda terms, we were able to implement Boolean logic! But Church
encoding goes further - we can also represent natural numbers and arithmetic
as lambda terms.</p>

<h3>Arithmetic</h3>

<p>Alonzo Church encoded numbers as applications of a function \(f\) to a term \(x\).</p>

<ul>
<li><code>0</code> means applying \(f\) 0 times to the term: \(0 := \lambda f.\lambda x.x\).</li>
<li><code>1</code> means applying \(f\) once to the term: \(1 := \lambda f.\lambda x.f x\).</li>
<li><code>2</code> means applying \(f\) twice: \(2 := \lambda f.\lambda x.f (f x)\).</li>
</ul>

<p>In general, the number <code>n</code> is represented by <code>n</code> applications of <code>f</code>: \(n :=
\lambda f.\lambda x.f (f (... (f x)) ... ))\) or \(n := \lambda f.\lambda x.
f^n(x)\).</p>

<p>In Python:</p>
<div class="highlight"><pre><span/><span class="n">ZERO</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span>
<span class="n">ONE</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="n">TWO</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">f</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">))</span>
<span class="o">...</span>
</pre></div>

<p>Note <code>ZERO</code> is the same as <code>FALSE</code>. With this definition of numbers, we can
define the successor function <code>SUCC</code> as a function that takes a number <code>n</code>
(represented with our Church encoding), the function <code>f</code>, the term <code>x</code>, and
applies <code>f</code> one more time. \(SUCC := \lambda n.\lambda f.\lambda x.f (n f x)\).</p>
<div class="highlight"><pre><span/><span class="n">SUCC</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">f</span><span class="p">(</span><span class="n">n</span><span class="p">(</span><span class="n">f</span><span class="p">)(</span><span class="n">x</span><span class="p">))</span>
</pre></div>

<p>We can define addition as \(PLUS := \lambda m.\lambda n.m \space SUCC \space n\).
Since we define a number as repeatedly applying a function, we express <code>m + n</code>
as applying <code>m</code> times the successor function <code>SUCC</code> to <code>n</code>.</p>
<div class="highlight"><pre><span/><span class="n">PLUS</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">m</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">m</span><span class="p">(</span><span class="n">SUCC</span><span class="p">)(</span><span class="n">n</span><span class="p">)</span>
</pre></div>

<p>We can similarly define multiplication as applications of the <code>PLUS</code> function:</p>
<div class="highlight"><pre><span/><span class="n">MUL</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">m</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="n">m</span><span class="p">(</span><span class="n">PLUS</span><span class="p">)(</span><span class="n">n</span><span class="p">)</span>
</pre></div>

<p>We'll stop here with arithmetic, but this should hopefully give you a sense of
the expressive power of lambda calculus.</p>

<h2>Combinators</h2>

<p>Some well-known lambda terms are called <em>combinators</em>:</p>

<ul>
<li>\(I\) is the identity combinator \(I := \lambda x.x\).</li>
<li>\(K\) is the constant combinator \(K := \lambda x.\lambda y.x\). When applied to
an argument \(x\), it returns a constant function \(K_x\) which returns \(x\) when
applied to any argument.</li>
<li>\(S\) is the substitution combinator \(S := \lambda x.\lambda y.\lambda z.x z
(y z)\). \(S\) takes 3 arguments, \(x\), \(y\), and \(z\), applies \(x\) to \(z\), then
applies the result of applying \(y\) to \(z\) to it.</li>
</ul>

<p>In Python:</p>
<div class="highlight"><pre><span/><span class="n">I</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">x</span>
<span class="n">K</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="n">x</span>
<span class="n">S</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">z</span><span class="p">:</span> <span class="n">x</span><span class="p">(</span><span class="n">z</span><span class="p">)(</span><span class="n">y</span><span class="p">(</span><span class="n">z</span><span class="p">))</span>
</pre></div>

<p>Turns out these 3 combinators can together express any lambda term. The SKI
combinators are the simplest <q>programming language</q> since they can express
anything expressable in lambda calculus, which we know is Turing-complete.</p>

<h3>The Y combinator</h3>

<p>Another interesting combinator is the \(Y\) combinator. In lambda calculus, there
is no way for a function to reference itself: within the body of a lambda like
<code>lambda x: ...</code> we can refer to the bound term <code>x</code>, but we can reference the
lambda itself. The implication is that we can't define, using this syntax,
self-referential functions. We can only pass functions as arguments. How can we
then implement recursion? With the \(Y\) combinator, of course.</p>

<p>Let's take an example: we can recursively define factorial as:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">fact</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
    <span class="k">return</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">else</span> <span class="n">n</span> <span class="o">*</span> <span class="n">fact</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>

<p>This works, but note we reference <code>fact()</code> within its body. In lambda calculus
we can't do that.</p>

<p>The \(Y\) combinator is defined as \(Y := \lambda f.(\lambda x.f (x x))(\lambda
x.f (x x))\).</p>
<div class="highlight"><pre><span/><span class="n">Y</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">(</span><span class="n">x</span><span class="p">)))(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">f</span><span class="p">(</span><span class="k">lambda</span> <span class="n">z</span><span class="p">:</span> <span class="n">x</span><span class="p">(</span><span class="n">x</span><span class="p">)(</span><span class="n">z</span><span class="p">)))</span>
</pre></div>

<p>Note the Python implementation is slightly different than the mathematical
definition. This has to do with the way in which Python evaluates arguments.
We won't go into the details here, but consider this a Python implementation
detail irrelevant to the lambda calculus discussion<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>.</p>

<p>Here is a lambda version of factorial:</p>
<div class="highlight"><pre><span/><span class="n">FACT</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">else</span> <span class="n">n</span> <span class="o">*</span> <span class="n">f</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>

<p>With this definition, we pass the function to call as an argument (<code>f</code>). We can
fully express this in lambda calculus (using Church numerals, arithmetic and
logic), but we'll keep the example simple. We can then use the \(Y\) combinator
like this:</p>
<div class="highlight"><pre><span/><span class="nb">print</span><span class="p">(</span><span class="n">Y</span><span class="p">(</span><span class="n">FACT</span><span class="p">)(</span><span class="mi">5</span><span class="p">))</span>  <span class="c1"># prints 120</span>
</pre></div>

<p>This should give you an intuitive understanding of how the \(Y\) combinator
works: we pass it our function and argument, and it enables the recursion
mechanism.</p>

<p>We can similarly implement Fibonacci as:</p>
<div class="highlight"><pre><span/><span class="n">FIB</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">2</span> <span class="k">else</span> <span class="n">f</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">f</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">Y</span><span class="p">(</span><span class="n">FIB</span><span class="p">)(</span><span class="mi">10</span><span class="p">))</span>  <span class="c1"># prints 55</span>
</pre></div>

<p>The powerful \(Y\) combinator can be used to define recursive functions in
programming languages that don't natively support recursion.</p>

<h1>Lists</h1>

<p>Let's also look at how we can express lists in lambda calculus. Let's start
with pairs. We can define a pair as \(PAIR := \lambda x.\lambda y.\lambda f.
f x y\). We can extract the first element of a pair with \(FIRST := \lambda p.
p \space T\) and the second one with \(SECOND := \lambda p.p \space F\).</p>
<div class="highlight"><pre><span/><span class="n">PAIR</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">)(</span><span class="n">y</span><span class="p">)</span>
<span class="n">FIRST</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">p</span><span class="p">:</span> <span class="n">p</span><span class="p">(</span><span class="n">TRUE</span><span class="p">)</span>
<span class="n">SECOND</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">p</span><span class="p">:</span> <span class="n">p</span><span class="p">(</span><span class="n">FALSE</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">FIRST</span><span class="p">(</span><span class="n">PAIR</span><span class="p">(</span><span class="mi">10</span><span class="p">)(</span><span class="mi">20</span><span class="p">)))</span>  <span class="c1"># prints 10</span>
<span class="nb">print</span><span class="p">(</span><span class="n">SECOND</span><span class="p">(</span><span class="n">PAIR</span><span class="p">(</span><span class="mi">10</span><span class="p">)(</span><span class="mi">20</span><span class="p">)))</span> <span class="c1"># prints 20</span>
</pre></div>

<p>We can define a <code>NULL</code> value as \(NULL := \lambda x.T\) and a test for <code>NULL</code> as
\(ISNULL := \lambda p.p (\lambda x.\lambda y.FALSE)\).</p>
<div class="highlight"><pre><span/><span class="n">NULL</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="n">TRUE</span>
<span class="n">ISNULL</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">p</span><span class="p">:</span> <span class="n">p</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">y</span><span class="p">:</span> <span class="n">FALSE</span><span class="p">)</span>
</pre></div>

<p>We can now define a linked list as either <code>NULL</code> (an empty list) or as a pair
consisting of a pair of elements - a head element and a tail list.</p>

<p>We can get the head of the list using <code>FIRST</code> and the tail using <code>SECOND</code>. Given
list \(L\), we can prepend an element \(x\) by forming the pair \((x, L)\).</p>
<div class="highlight"><pre><span/><span class="n">HEAD</span> <span class="o">=</span> <span class="n">FIRST</span>
<span class="n">TAIL</span> <span class="o">=</span> <span class="n">SECOND</span>
<span class="n">PREPEND</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">xs</span><span class="p">:</span> <span class="n">PAIR</span><span class="p">(</span><span class="n">x</span><span class="p">)(</span><span class="n">xs</span><span class="p">)</span>
</pre></div>

<p>We can build a list by prepending elements to <code>NULL</code>, and traverse it using
<code>HEAD</code> and <code>TAIL</code>:</p>
<div class="highlight"><pre><span/><span class="c1"># Build the list [10, 20, 30]</span>
<span class="n">L</span> <span class="o">=</span> <span class="n">PREPEND</span><span class="p">(</span><span class="mi">10</span><span class="p">)(</span><span class="n">PREPEND</span><span class="p">(</span><span class="mi">20</span><span class="p">)(</span><span class="n">PREPEND</span><span class="p">(</span><span class="mi">30</span><span class="p">)(</span><span class="n">NULL</span><span class="p">)))</span>

<span class="nb">print</span><span class="p">(</span><span class="n">HEAD</span><span class="p">(</span><span class="n">TAIL</span><span class="p">(</span><span class="n">L</span><span class="p">)))</span> <span class="c1"># prints 20</span>
</pre></div>

<p>Appending is more interesting: if our list is represented as a pair of head and
tail, we need to <q>traverse</q> the list until we reach the end. This sounds a lot
like a recursive function: appending <code>x</code> to <code>xs</code> entails returning the pair
<code>PAIR(x, NULL)</code> if <code>xs</code> is <code>NULL</code>, else the pair <code>PAIR(HEAD(xs), APPEND(TAIL(xs,
x)))</code>. Fortunately, we just looked at the \(Y\) combinator which allows us
to express this.</p>

<p>Here is a simplified, readable implementation, using Python tuples:</p>
<div class="highlight"><pre><span/><span class="n">_append</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">xs</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> \
    <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">xs</span> <span class="k">else</span> <span class="p">(</span><span class="n">xs</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">f</span><span class="p">(</span><span class="n">xs</span><span class="p">[</span><span class="mi">1</span><span class="p">])(</span><span class="n">x</span><span class="p">))</span>

<span class="n">append</span> <span class="o">=</span> <span class="n">Y</span><span class="p">(</span><span class="n">_append</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">append</span><span class="p">(</span><span class="n">append</span><span class="p">(</span><span class="n">append</span><span class="p">(</span><span class="kc">None</span><span class="p">)(</span><span class="mi">10</span><span class="p">))(</span><span class="mi">20</span><span class="p">))(</span><span class="mi">30</span><span class="p">))</span>

<span class="c1"># This will print (10, (20, (30, None)))</span>
</pre></div>

<p>We can express the same using the lambdas we defined above (<code>NULL</code>, <code>ISNULL</code>,
<code>PAIR</code>, <code>HEAD</code>, <code>TAIL</code>):</p>
<div class="highlight"><pre><span/><span class="n">_APPEND</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">f</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">xs</span><span class="p">:</span> <span class="k">lambda</span> <span class="n">x</span><span class="p">:</span> \
    <span class="n">ISNULL</span><span class="p">(</span><span class="n">xs</span><span class="p">)</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">_</span><span class="p">:</span> <span class="n">PAIR</span><span class="p">(</span><span class="n">x</span><span class="p">)(</span><span class="n">NULL</span><span class="p">))</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">_</span><span class="p">:</span> <span class="n">PAIR</span><span class="p">(</span><span class="n">HEAD</span><span class="p">(</span><span class="n">xs</span><span class="p">))(</span><span class="n">f</span><span class="p">(</span><span class="n">TAIL</span><span class="p">(</span><span class="n">xs</span><span class="p">))(</span><span class="n">x</span><span class="p">)))</span> <span class="p">(</span><span class="n">TRUE</span><span class="p">)</span>

<span class="n">APPEND</span> <span class="o">=</span> <span class="n">Y</span><span class="p">(</span><span class="n">_APPEND</span><span class="p">)</span>

<span class="n">L</span> <span class="o">=</span> <span class="n">APPEND</span><span class="p">(</span><span class="n">APPEND</span><span class="p">(</span><span class="n">APPEND</span><span class="p">(</span><span class="n">NULL</span><span class="p">)(</span><span class="mi">10</span><span class="p">))(</span><span class="mi">20</span><span class="p">))(</span><span class="mi">30</span><span class="p">)</span>

<span class="nb">print</span><span class="p">(</span><span class="n">HEAD</span><span class="p">(</span><span class="n">L</span><span class="p">))</span>       <span class="c1"># prints 10</span>
<span class="nb">print</span><span class="p">(</span><span class="n">HEAD</span><span class="p">(</span><span class="n">TAIL</span><span class="p">(</span><span class="n">L</span><span class="p">)))</span> <span class="c1"># prints 20</span>
</pre></div>

<p>We covered logic, arithmetic, combinators, pairs, and lists, all expressed as
lambda terms. Let's also sketch a proof of Turing completeness, like we did in
previous posts.</p>

<h2>A sketch of Turing completeness</h2>

<p>We're calling this a <q>sketch</q>, as lambda notation is not easy to read. We will
instead look at an implementation using more Python syntax than just lambdas,
but we will only use constructs which we know can be expressed in lambda
calculus.</p>

<p>As usual, we will emulate another system which we know to be Turing-complete.
In <a href="https://vladris.com/blog/2022/05/20/computability-part-3-tag-systems.html">part 3</a>
we looked at tag systems. We talked about cyclic tag systems, which can emulate
m-tag systems, which are Turing-complete. As a reminder, a cyclic tag system is
implemented as a set of binary strings (strings containing only <code>0</code>s and <code>1</code>s)
which are production rules, and we process a binary input string by popping the
head of the string and, if it is equal to <code>1</code>, appending the current production
rule to the string. We cycle through the production rules at each step. This is
the code we used in the previous post:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="c1"># Keeps track of current production</span>
    <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="c1"># Repeat until the string is empty</span>
    <span class="k">while</span> <span class="n">string</span><span class="p">:</span>
        <span class="n">string</span> <span class="o">=</span> <span class="n">string</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="o">+</span> <span class="p">(</span><span class="n">productions</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">if</span> <span class="n">string</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'1'</span> <span class="k">else</span> <span class="s1">''</span><span class="p">)</span>

        <span class="c1"># Update current production</span>
        <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">productions</span><span class="p">):</span>
            <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>

        <span class="k">yield</span> <span class="n">string</span>
</pre></div>

<p>We used the productions <code>11</code>, <code>01</code>, and <code>00</code> and the input <code>1</code>:</p>
<div class="highlight"><pre><span/><span class="n">productions</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'11'</span><span class="p">,</span> <span class="s1">'01'</span><span class="p">,</span> <span class="s1">'00'</span><span class="p">]</span>

<span class="n">string</span> <span class="o">=</span> <span class="s1">'1'</span>

<span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">for</span> <span class="n">string</span> <span class="ow">in</span> <span class="n">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
</pre></div>

<p>Let's sketch an alternative implementation using the constructs we covered in
this post.</p>

<p>First, we can describe our production rules as lists of Boolean values. We
know how to represent Boolean values (<code>TRUE</code> and <code>FALSE</code>), and how to build
a list using <code>PAIR</code>. Our productions can be represented as:</p>
<div class="highlight"><pre><span/><span class="n">p1</span> <span class="o">=</span> <span class="p">(</span><span class="kc">True</span><span class="p">,</span> <span class="p">(</span><span class="kc">True</span><span class="p">,</span> <span class="kc">None</span><span class="p">))</span>   <span class="c1"># PAIR(TRUE)(PAIR(TRUE)(NULL))</span>
<span class="n">p2</span> <span class="o">=</span> <span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="p">(</span><span class="kc">True</span><span class="p">,</span> <span class="kc">None</span><span class="p">))</span>  <span class="c1"># PAIR(FALSE)(PAIR(TRUE)(NULL))</span>
<span class="n">p3</span> <span class="o">=</span> <span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="p">(</span><span class="kc">False</span><span class="p">,</span> <span class="kc">None</span><span class="p">))</span> <span class="c1"># PAIR(FALSE)(PAIR(FALSE)(NULL))</span>

<span class="n">productions</span> <span class="o">=</span> <span class="p">(</span><span class="n">p1</span><span class="p">,</span> <span class="p">(</span><span class="n">p2</span><span class="p">,</span> <span class="p">(</span><span class="n">p3</span><span class="p">,</span> <span class="kc">None</span><span class="p">)))</span>
</pre></div>

<p>We can cycle through the list by processing the head, then appending it to
the tail of the list. Here are simpler implementations of our list processing
functions over Python tuples (though we know how to do these using only lambda
terms):</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">head</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>

<span class="k">def</span><span class="w"> </span><span class="nf">tail</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">p</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>

<span class="k">def</span><span class="w"> </span><span class="nf">append</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">x</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">xs</span> <span class="k">else</span> <span class="p">(</span><span class="n">head</span><span class="p">(</span><span class="n">xs</span><span class="p">),</span> <span class="n">append</span><span class="p">(</span><span class="n">tail</span><span class="p">(</span><span class="n">xs</span><span class="p">),</span> <span class="n">x</span><span class="p">))</span>

<span class="c1"># If we want to cycle through our productions, we can do:</span>
<span class="c1"># productions = append(tail(productions), head(productions))</span>
</pre></div>

<p>We'll also need a function to concatenate two lists. We can easily build this
on top of <code>append()</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">concat</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">ys</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">xs</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">ys</span> <span class="k">else</span> <span class="n">concat</span><span class="p">(</span><span class="n">append</span><span class="p">(</span><span class="n">xs</span><span class="p">,</span> <span class="n">head</span><span class="p">(</span><span class="n">ys</span><span class="p">)),</span> <span class="n">tail</span><span class="p">(</span><span class="n">ys</span><span class="p">))</span>
</pre></div>

<p>While we still have <code>ys</code>, we append the head of <code>ys</code> to <code>xs</code>, then recurse
with the tail of <code>ys</code>.</p>

<p>We process our input string as follows: if it is empty, we are done. If not,
if the head is <code>1</code>, we concatenate our current production to the end of the
string, and recurse, cycling productions:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="nb">input</span><span class="p">):</span>
    <span class="k">return</span> <span class="kc">None</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">input</span> <span class="k">else</span> \
        <span class="n">cyclic_tag_system</span><span class="p">(</span>
            <span class="c1"># Cycle productions</span>
            <span class="n">append</span><span class="p">(</span><span class="n">tail</span><span class="p">(</span><span class="n">productions</span><span class="p">),</span> <span class="n">head</span><span class="p">(</span><span class="n">productions</span><span class="p">)),</span>
            <span class="c1"># If head is True, concatenate head production. Pop head input either way.</span>
            <span class="n">concat</span><span class="p">(</span><span class="n">tail</span><span class="p">(</span><span class="nb">input</span><span class="p">),</span> <span class="n">head</span><span class="p">(</span><span class="n">productions</span><span class="p">))</span> <span class="k">if</span> <span class="n">head</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span> <span class="k">else</span> <span class="n">tail</span><span class="p">(</span><span class="nb">input</span><span class="p">))</span>
</pre></div>

<p>Let's throw in a <code>print()</code> and run this on the same input as our original
example:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="nb">input</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
    <span class="k">return</span> <span class="kc">None</span> <span class="k">if</span> <span class="ow">not</span> <span class="nb">input</span> <span class="k">else</span> \
        <span class="n">cyclic_tag_system</span><span class="p">(</span>
            <span class="c1"># Cycle productions</span>
            <span class="n">append</span><span class="p">(</span><span class="n">tail</span><span class="p">(</span><span class="n">productions</span><span class="p">),</span> <span class="n">head</span><span class="p">(</span><span class="n">productions</span><span class="p">)),</span>
            <span class="c1"># If head is True, concatenate head production. Pop head input either way.</span>
            <span class="n">concat</span><span class="p">(</span><span class="n">tail</span><span class="p">(</span><span class="nb">input</span><span class="p">),</span> <span class="n">head</span><span class="p">(</span><span class="n">productions</span><span class="p">))</span> <span class="k">if</span> <span class="n">head</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span> <span class="k">else</span> <span class="n">tail</span><span class="p">(</span><span class="nb">input</span><span class="p">))</span>

<span class="c1"># The input is equivalent to the string '1'</span>
<span class="n">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="p">(</span><span class="kc">True</span><span class="p">,</span> <span class="kc">None</span><span class="p">))</span>
</pre></div>

<p>This should produce output very similar to our original <code>cyclic_tag_system()</code>,
but using lists of Booleans instead of strings of <code>0</code>s and <code>1</code>s.</p>

<p>We emulated a cyclic tag system in lambda calculus - well, we didn't write all
the code as lambda terms, but everything is expressed as one-liner functions
that use only if-then-else expressions, lists (pair, head, tail), and recursion
(for which we have the \(Y\) combinator).</p>

<p>Lambda calculus has been extremely influential in computer science - it is the
root of functional programming. LISP, one of the earliest programming
languages, is heavily influenced by lambda calculus. Many ideas, like anonymous
functions, also known as <em>lambdas</em>, are now broadly available in most modern
programming languages (Python even uses the keyword <code>lambda</code> for these, as we
saw in this post).</p>

<h2>Summary</h2>

<p>In this post we covered lambda calculus:</p>

<ul>
<li>Lambda terms, including <em>variables</em>, <em>abstractions</em>, and <em>applications</em>.</li>
<li>Reductions: \(\alpha\)-equivalence, \(\beta\)-reduction, and \(\eta\)-reduction.</li>
<li>Church encoding for Boolean logic and arithmetic using lambda terms.</li>
<li>Combinators: the \(S\), \(K\), and \(I\) combinators which are sufficient to encode
all lambda terms, and the \(Y\) combinator which enables recursion.</li>
<li>Pairs and lists (defined using pairs), including an <code>append</code> operation.</li>
<li>Emulating a cyclic tag systems in lambda calculus.</li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>See <a href="https://en.wikipedia.org/wiki/Church%E2%80%93Turing_thesis">this Wikipedia article</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>This <a href="https://kigawas.me/posts/y-combinator-in-python/">blog post</a> goes
  into the details if you are curious. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Fri, 14 Oct 2022 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/09/02/computability-part-7-machine-implementation-practicalities.html</link>
      <guid>https://vladris.com/blog/2022/09/02/computability-part-7-machine-implementation-practicalities.html</guid>
      <title><![CDATA[Computability Part 7: Machine Implementation Practicalities]]></title>
      <description><![CDATA[<h1>Computability Part 7: Machine Implementation Practicalities</h1>

<p>In the <a href="https://vladris.com/blog/2022/07/31/computability-part-6-von-neumann-architecture.html">previous
post</a>
we covered the von Neumann architecture and even built a small VM
implementing the different components. Such naÃ¯ve implementation does
make for a very inefficient machine though. In this post, we'll dive a
bit deeper into machine architectures (virtual and physical) and discuss
some of the implementation details. We'll talk about processing:
register and stack-based; we'll talk about memory: word size, byte and
word addressing; finally, we'll talk about I/O: port and memory mapped.
Note these are all machines that conform to the von Neumann
architecture, with the same high-level components. We're just double
clicking to the next level of implementation details.</p>

<h2>Register machines</h2>

<p>The VM we implemented in our previous post simply operated directly over
the memory. This works for a toy example, but moving data from memory to
the CPU and back is costly. That's why modern CPUs employ multiple
layers of caching (we won't cover these in this post), and rely on a
set of <em>registers</em> to perform operations.</p>

<p>Registers can store a number of bits (the <em>word size</em>, more on it below)
and operations are performed using registers. For example, to add two
numbers, the machine would load one number into register <code>R0</code>, the
second number into register <code>R1</code>, add the values stored in registers
<code>R0</code> and <code>R1</code>, then finally save the result back to memory:</p>
<div class="highlight"><pre><span/>mov r0 @&lt;memory address 1&gt; # Move the value from memory address 1 to r0
mov r1 @&lt;memory address 2&gt; # Move the value from memory address 2 to r1
add r0 r1 # Add the values storing the result in r0
mov @&lt;memory address 3&gt; r0 # Move the value from r0 to memory address 3
</pre></div>

<p>Some register are used for general computation. These are called
<em>general-purpose registers</em>. Other register have specialized purposes.
For example, the program counter which keeps track of the instruction to
be executed is usually implemented as an <code>IP</code> (instruction pointer) or
<code>PC</code> (program counter) register.</p>

<p>The original 8088 Intel processor had 14 registers. Modern Intel
processors have significantly more registers<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>, though many of them
are special-purpose. ARM processors have 17 registers<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>, 13 of which
are general purpose.</p>

<p>Let's emulate a simple CPU with 4 general purpose registers and a
program counter register to get the feel of it. We will only implement
<code>mov</code> (move) and <code>add</code> instructions for this example. Our implementation
will check the 16th bit of an argument to determine whether it refers to
a register (if <code>0</code>) or to a memory location (if <code>1</code>).</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">CPU</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memory</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">memory</span> <span class="o">=</span> <span class="n">memory</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">registers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span> <span class="c1"># r0, r1, r2, r3, pc</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">registers</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">):</span>
            <span class="n">instr</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">registers</span><span class="p">[</span><span class="mi">4</span><span class="p">]:</span><span class="bp">self</span><span class="o">.</span><span class="n">registers</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">instr</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">registers</span><span class="p">[</span><span class="mi">4</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">3</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">get_at</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
        <span class="c1"># 16th bit tells us whether this refers to a register or memory</span>
        <span class="k">if</span> <span class="n">arg</span> <span class="o">&amp;</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">):</span> <span class="c1"># Memory address</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">arg</span> <span class="o">^</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">)]</span>
        <span class="k">else</span><span class="p">:</span> <span class="c1"># Register</span>
            <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">registers</span><span class="p">[</span><span class="n">arg</span><span class="p">]</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">set_at</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="c1"># 16th bit tells us whether this refers to a register or memory</span>
        <span class="k">if</span> <span class="n">arg</span> <span class="o">&amp;</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">):</span> <span class="c1"># Memory address</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">arg</span> <span class="o">^</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">)]</span> <span class="o">=</span> <span class="n">value</span>
        <span class="k">else</span><span class="p">:</span> <span class="c1"># Register</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">registers</span><span class="p">[</span><span class="n">arg</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instr</span><span class="p">,</span> <span class="n">arg1</span><span class="p">,</span> <span class="n">arg2</span><span class="p">):</span>
        <span class="k">match</span> <span class="n">instr</span><span class="p">:</span>
            <span class="k">case</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># mov</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">set_at</span><span class="p">(</span><span class="n">arg1</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_at</span><span class="p">(</span><span class="n">arg2</span><span class="p">))</span>
            <span class="k">case</span> <span class="mi">1</span><span class="p">:</span> <span class="c1"># add</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">set_at</span><span class="p">(</span><span class="n">arg1</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_at</span><span class="p">(</span><span class="n">arg1</span><span class="p">)</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_at</span><span class="p">(</span><span class="n">arg2</span><span class="p">))</span>
</pre></div>

<p>Here is how it would run a small program that adds two numbers and
stores the result:</p>
<div class="highlight"><pre><span/><span class="n">program</span> <span class="o">=</span> <span class="p">[</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">15</span> <span class="o">|</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">),</span> <span class="c1"># mov r0 @15</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">16</span> <span class="o">|</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">),</span> <span class="c1"># mov r1 @16</span>
    <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>              <span class="c1"># add r0 r1</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">17</span> <span class="o">|</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">),</span> <span class="mi">0</span><span class="p">,</span> <span class="c1"># mov @17 r0</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">18</span> <span class="o">|</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="mi">15</span><span class="p">),</span> <span class="c1"># mov pc @18 - this ends execution</span>
    <span class="mi">40</span><span class="p">,</span>                   <span class="c1"># this is @15</span>
    <span class="mi">2</span><span class="p">,</span>                    <span class="c1"># this is @16</span>
    <span class="mi">0</span><span class="p">,</span>                    <span class="c1"># this is @17</span>
    <span class="mi">10000</span>                 <span class="c1"># this is @18</span>
<span class="p">]</span>

<span class="c1">## Load program into memory</span>
<span class="n">memory</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">10000</span>
<span class="n">memory</span> <span class="o">=</span> <span class="n">program</span> <span class="o">+</span> <span class="n">memory</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">program</span><span class="p">):]</span>

<span class="nb">print</span><span class="p">(</span><span class="n">memory</span><span class="p">[</span><span class="mi">17</span><span class="p">])</span> <span class="c1"># Should print 0</span>

<span class="n">CPU</span><span class="p">(</span><span class="n">memory</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>

<span class="nb">print</span><span class="p">(</span><span class="n">memory</span><span class="p">[</span><span class="mi">17</span><span class="p">])</span> <span class="c1"># Should print 42</span>
</pre></div>

<p>We're doing a bunch of stuff <q>by hand</q>, like loading the program into
memory and not using an assembler to implement the program. That's
because we're only focusing on the register-based processing. You can
update the assembler in the previous post to target this VM as an
exercise.</p>

<h2>Stack machines</h2>

<p>An alternative to registers is to use a stack for storage. While
hardware stack machines are not unheard of, register machines easily
outperform them so most CPUs you interact with are register-based. That
said, stack machines are a popular choice for virtual machines - they
are easier to implement and port to different systems and the stack
keeps the data being processed close together which helps with
performance when running the VM on a physical machine. A few examples:
JVM (the Java virtual machine), the CLR (the .NET virtual machine),
CPython's VM (the VM for the reference Python implementation) are all
stack-based.</p>

<p>The example we used above of adding two numbers would look like this on
a stack machine: push the first number onto the stack, push the second
number onto the stack, add the numbers (which would pop the two numbers
from the stack and replace them with their sum), then pop the value from
the stack and store it in memory.</p>
<div class="highlight"><pre><span/>push @&lt;memory address 1&gt; # Push a value from memory address 1
push @&lt;memory address 2&gt; # Push a value from memory address 2
add # Add the top two values
pop @&lt;memory address 3&gt; # Pop the top of the stack and store at memory address 3
</pre></div>

<p>Another advantage of stack machines is in general the instructions tend
to be shorter. As you can see above, for most instructions that move
data around, we don't need to specify both a source and a destination
since the stack is implied.</p>

<p>Let's emulate a simple stack VM with only <code>push</code>, <code>add</code>, and <code>pop</code>
instructions, plus a <code>jmp</code> (jump) instruction so we can use the same
mechanism to terminate:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">CPU</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memory</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">memory</span> <span class="o">=</span> <span class="n">memory</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">=</span> <span class="p">[],</span> <span class="mi">0</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">):</span>
            <span class="n">instr</span><span class="p">,</span> <span class="n">arg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">pc</span><span class="p">:</span><span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">instr</span><span class="p">,</span> <span class="n">arg</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">+=</span> <span class="mi">2</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instr</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
        <span class="k">match</span> <span class="n">instr</span><span class="p">:</span>
            <span class="k">case</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># push</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">arg</span><span class="p">])</span>
            <span class="k">case</span> <span class="mi">1</span><span class="p">:</span> <span class="c1"># pop</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">arg</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
            <span class="k">case</span> <span class="mi">2</span><span class="p">:</span> <span class="c1"># jmp</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
            <span class="k">case</span> <span class="mi">3</span><span class="p">:</span> <span class="c1"># add</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">())</span>
</pre></div>

<p>Here is how it would run a small program that adds two numbers and
stores the result:</p>
<div class="highlight"><pre><span/><span class="n">program</span> <span class="o">=</span> <span class="p">[</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">12</span><span class="p">,</span> <span class="c1"># push @12</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">13</span><span class="p">,</span> <span class="c1"># push @13</span>
    <span class="mi">3</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>  <span class="c1"># add</span>
    <span class="mi">1</span><span class="p">,</span> <span class="mi">14</span><span class="p">,</span> <span class="c1"># pop @14</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">15</span><span class="p">,</span> <span class="c1"># push @15</span>
    <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>  <span class="c1"># jmp</span>
    <span class="mi">40</span><span class="p">,</span>    <span class="c1"># this is @12</span>
    <span class="mi">2</span><span class="p">,</span>     <span class="c1"># this is @13</span>
    <span class="mi">0</span><span class="p">,</span>     <span class="c1"># this is @14</span>
    <span class="mi">10000</span><span class="p">,</span> <span class="c1"># this is @15</span>
<span class="p">]</span>

<span class="c1">## Load program into memory</span>
<span class="n">memory</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">10000</span>
<span class="n">memory</span> <span class="o">=</span> <span class="n">program</span> <span class="o">+</span> <span class="n">memory</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">program</span><span class="p">):]</span>

<span class="nb">print</span><span class="p">(</span><span class="n">memory</span><span class="p">[</span><span class="mi">14</span><span class="p">])</span> <span class="c1"># Should print 0</span>

<span class="n">CPU</span><span class="p">(</span><span class="n">memory</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>

<span class="nb">print</span><span class="p">(</span><span class="n">memory</span><span class="p">[</span><span class="mi">14</span><span class="p">])</span> <span class="c1"># Should print 42</span>
</pre></div>

<p>Contrast the implementation with the register-based one: the latter VM
only needs 1 argument for the instructions we implemented and the
program is slightly shorter.</p>

<p>So far we focused on how data is processed. Let's also look at the
different ways of referencing data.</p>

<h2>Word size</h2>

<p>We've been using Python for our toy implementations. Python supports
arbitrarily large integers, so a list of numbers in Python (the way we
implemented our memory) doesn't imply much in terms of bits and bytes.
Bits and bytes do become important for physical machines and serious VMs
implemented in languages closer to the metal.</p>

<p>First, let's talk about <em>word size</em>. A <em>word</em> is the fixed-size unit of
computation for a CPU. It's size is the number of bits. For example, a
16-bit processor has a word-size of 16-bits.</p>

<p>Applied to registers, this would mean that a machine register can hold
at most 16 bits (a value between 0 and 65535). Operations within the
value range are blazingly fast, as they run natively. If we need to
process larger values, we need to do extra work to chunk the values into
words and process these in turn. For example we can split a 32-bit value
into two 16-bit values, process them separately, then concatenate the
result. This obviously impacts performance. The point being that we are
not necessarily limited to the word size, but processing larger values
becomes much costlier.</p>

<p>Applied to memory addresses, this would mean how pointers are
represented and what range of values can be addressed. For example, if
the word size is 16 bits, then a pointer can point to any one of 65536
distinct memory locations.</p>

<p>An architecture can use the same word size for both registers and
pointers, or different word sizes for different concerns. Commonly, a
single word size is used (and, potentially, fractions or multiples of it
for special concerns), that's why it's common to refer to a processor
as a 32-bit processor, 64-bit processor etc.</p>

<h2>Byte and word addressing</h2>

<p>An implication of word size applied to memory addressing is how the
machine accesses memory. Some architectures allow <em>byte addressing</em>,
which means a pointer points to a specific byte in memory, while others
support only <em>word addressing</em>, which means a pointer points to a word
in memory.</p>

<p>This is another important decision when designing a computer. If we want
to be able to address individual bytes, a 16 bit pointer can refer to
any of 65536 bytes. That is 64 Kb. If our memory is larger than that, a
pointer won't be able to address higher locations.</p>

<p>On the other hand, if we make our memory word-addressable, for our
16-bit example, a pointer can refer to any of 65536 16-bit words. 16
bits are 2 bytes, so our memory's upper limit is 131072 bytes (65536 x
2), which is 128 Kb. We can now refer to higher memory addresses, but we
can't address individual bytes as before - address 0 is no longer the
byte at 0, is the whole 2-byte word (since address 1 refers to the next
2 bytes and so on).</p>

<p>This difference becomes even more dramatic for higher word sizes. A
32-bit pointer can address 4294967296 bytes (up to 4 Gb of memory).
Alternately, with word addressing, the same pointer can cover 16 Gb.</p>

<p>On the flip side, word-addressing is less efficient when the unit of
processing is smaller. Let's take text editing as an example. Say we
want to update a one byte character, like a UTF-8 encoded common
character like <code>a</code>. If we can refer to it directly, we can load,
process, and update its memory location using a pointer. If, on the
other hand, this character is part of a larger word, we would have to
process the whole word to extract the character we care about (masking
bits we don't need to process), apply the update to the whole word, and
write this word back to memory.</p>

<p>So depending on the scenario, byte or word addressing might make things
faster or slower. Byte addressing is great for text processing -
document authoring, HTML, writing code etc. Word addressing unlocks
larger memory sizes and is great for crunching numbers - math, graphics
etc.</p>

<p>Another important design decision is how to handle I/O.</p>

<h2>Port-mapped I/O</h2>

<p>One way to connect I/O to the system is through specific CPU
instructions. For example, the CPU might have an <code>inp</code> instruction used
to consume input and an <code>out</code> instruction used to send output. Programs
can use these instructions to perform I/O. This is called <em>port-mapped
I/O</em>, as I/O is achieved by connecting devices to the CPU via dedicated
ports.</p>

<p>For example, let's extend our stack machine with an <code>out</code> instruction
(also connecting an output to it):</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">CPU</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memory</span><span class="p">,</span> <span class="n">out</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">out</span> <span class="o">=</span> <span class="n">memory</span><span class="p">,</span> <span class="n">out</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">=</span> <span class="p">[],</span> <span class="mi">0</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">):</span>
            <span class="n">instr</span><span class="p">,</span> <span class="n">arg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">pc</span><span class="p">:</span><span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">instr</span><span class="p">,</span> <span class="n">arg</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">+=</span> <span class="mi">2</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instr</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
        <span class="k">match</span> <span class="n">instr</span><span class="p">:</span>
            <span class="k">case</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># push</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">arg</span><span class="p">])</span>
            <span class="k">case</span> <span class="mi">1</span><span class="p">:</span> <span class="c1"># pop</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">arg</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
            <span class="k">case</span> <span class="mi">2</span><span class="p">:</span> <span class="c1"># jmp</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
            <span class="k">case</span> <span class="mi">3</span><span class="p">:</span> <span class="c1"># add</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">())</span>
            <span class="k">case</span> <span class="mi">4</span><span class="p">:</span> <span class="c1"># out</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">out</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">())</span>
</pre></div>

<p>Here is a program that prints <q>Hello</q>:</p>
<div class="highlight"><pre><span/><span class="n">program</span> <span class="o">=</span> <span class="p">[</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">24</span><span class="p">,</span> <span class="c1"># push @24</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">25</span><span class="p">,</span> <span class="c1"># push @25</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">26</span><span class="p">,</span> <span class="c1"># push @26</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">27</span><span class="p">,</span> <span class="c1"># push @27</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="c1"># push @28</span>
    <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>  <span class="c1"># out</span>
    <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>  <span class="c1"># out</span>
    <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>  <span class="c1"># out</span>
    <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>  <span class="c1"># out</span>
    <span class="mi">4</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>  <span class="c1"># out</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">29</span><span class="p">,</span> <span class="c1"># push @29</span>
    <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>  <span class="c1"># jmp</span>
    <span class="mi">111</span><span class="p">,</span>   <span class="c1"># this is @24</span>
    <span class="mi">108</span><span class="p">,</span>   <span class="c1"># this is @25</span>
    <span class="mi">108</span><span class="p">,</span>   <span class="c1"># this is @26</span>
    <span class="mi">101</span><span class="p">,</span>   <span class="c1"># this is @27</span>
    <span class="mi">72</span><span class="p">,</span>    <span class="c1"># this is @28</span>
    <span class="mi">10000</span><span class="p">,</span> <span class="c1"># this is @29</span>
<span class="p">]</span>

<span class="c1">## Load program into memory</span>
<span class="n">memory</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">10000</span>
<span class="n">memory</span> <span class="o">=</span> <span class="n">program</span> <span class="o">+</span> <span class="n">memory</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">program</span><span class="p">):]</span>

<span class="k">def</span><span class="w"> </span><span class="nf">out</span><span class="p">(</span><span class="n">val</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">val</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span>

<span class="n">CPU</span><span class="p">(</span><span class="n">memory</span><span class="p">,</span> <span class="n">out</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>

<h2>Memory-mapped I/O</h2>

<p>An alternative to port-mapped I/O is <em>memory-mapped I/O</em>. In this case,
a certain address range of memory is used for I/O operations. That is,
from the CPU's perspective, memory and I/O are addressed identically.
But depending on the address range, data might reside in memory or it
might actually come from/go to an I/O device.</p>

<p>Let's enhance our memory implementation (which so far was just an
array) to support mapped I/O. In this case, any values written at
address 1000 will be instead printed on screen:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">MappedMemory</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">program</span><span class="p">):</span>
        <span class="c1"># MappedMemory wraps a list</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">memory</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">10000</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">memory</span> <span class="o">=</span> <span class="n">program</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">program</span><span class="p">):]</span>

    <span class="k">def</span><span class="w"> </span><span class="fm">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># Use underlying list's __len__</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="o">.</span><span class="fm">__len__</span><span class="p">()</span>

    <span class="k">def</span><span class="w"> </span><span class="fm">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">):</span>
        <span class="c1"># Index in wrapped list</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>

    <span class="k">def</span><span class="w"> </span><span class="fm">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
        <span class="c1"># If key is 1000, print</span>
        <span class="k">if</span> <span class="n">key</span> <span class="o">==</span> <span class="mi">1000</span><span class="p">:</span>
            <span class="nb">print</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">value</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span>
        <span class="c1"># Otherwise set in underlying list</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
</pre></div>

<p>And here is the corresponding program that prints <q>Hello</q> (using the
stack CPU without the <code>out</code> instruction and connected output):</p>
<div class="highlight"><pre><span/><span class="n">program</span> <span class="o">=</span> <span class="p">[</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">24</span><span class="p">,</span> <span class="c1"># push @24</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">25</span><span class="p">,</span> <span class="c1"># push @25</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">26</span><span class="p">,</span> <span class="c1"># push @26</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">27</span><span class="p">,</span> <span class="c1"># push @27</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="c1"># push @28</span>
    <span class="mi">1</span><span class="p">,</span> <span class="mi">1000</span><span class="p">,</span> <span class="c1"># pop @1000</span>
    <span class="mi">1</span><span class="p">,</span> <span class="mi">1000</span><span class="p">,</span> <span class="c1"># pop @1000</span>
    <span class="mi">1</span><span class="p">,</span> <span class="mi">1000</span><span class="p">,</span> <span class="c1"># pop @1000</span>
    <span class="mi">1</span><span class="p">,</span> <span class="mi">1000</span><span class="p">,</span> <span class="c1"># pop @1000</span>
    <span class="mi">1</span><span class="p">,</span> <span class="mi">1000</span><span class="p">,</span> <span class="c1"># pop @1000</span>
    <span class="mi">0</span><span class="p">,</span> <span class="mi">29</span><span class="p">,</span>   <span class="c1"># push @29</span>
    <span class="mi">2</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span>    <span class="c1"># jmp</span>
    <span class="mi">111</span><span class="p">,</span>     <span class="c1"># this is @24</span>
    <span class="mi">108</span><span class="p">,</span>     <span class="c1"># this is @25</span>
    <span class="mi">108</span><span class="p">,</span>     <span class="c1"># this is @26</span>
    <span class="mi">101</span><span class="p">,</span>     <span class="c1"># this is @27</span>
    <span class="mi">72</span><span class="p">,</span>      <span class="c1"># this is @28</span>
    <span class="mi">10000</span><span class="p">,</span>   <span class="c1"># this is @29</span>
<span class="p">]</span>

<span class="c1">## Load program into memory</span>
<span class="n">memory</span> <span class="o">=</span> <span class="n">MappedMemory</span><span class="p">(</span><span class="n">program</span><span class="p">)</span>

<span class="n">CPU</span><span class="p">(</span><span class="n">memory</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>

<p>Note in this program we repeatedly <q>set</q> the value at address 1000
which is mapped to our output device (<code>print()</code>).</p>

<h2>Summary</h2>

<p>In this post we discussed some of the implementation details of machines
and virtual machines:</p>

<ul>
<li>  Register machines, which are high-performance designs for physical
machines.</li>
<li>  Stack machines, which are simple, portable, and great alternatives
for VMs.</li>
<li>  Word size, as the unit of data used by the machine for different
purposes.</li>
<li>  Word-addressable memory, which is great for computation intensive
scenarios.</li>
<li>  Byte-addressable memory, which is best for text-processing
scenarios.</li>
<li>  Port-mapped I/O, where special CPU instructions are used for input
and ouptut.</li>
<li>  Memory-mapped I/O, where reserved address ranges of memory are used
for I/O and the CPU can access I/O just like it does memory.</li>
</ul>

<h3>Bonus</h3>

<p>A few years back I implemented a toy VM with 7 registers, 16 op codes,
128 KB of memory, and port-mapped I/O in 121 lines of C++. It comes with
an assembler, examples, and, of course, a Brainfuck interpreter. Linking
it here for reference: <a href="https://github.com/vladris/pixie">Pixie</a>.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>See <a href="https://reverseengineering.stackexchange.com/questions/19693/how-many-registers-does-an-x86-64-cpu-actually-have%3E">this SO question</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>See the <a href="https://developer.arm.com/documentation/dui0473/c/overview-of-the-arm-architecture/arm-registers?lang=en%3E">ARM documentation</a>. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Fri, 02 Sep 2022 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/07/31/computability-part-6-von-neumann-architecture.html</link>
      <guid>https://vladris.com/blog/2022/07/31/computability-part-6-von-neumann-architecture.html</guid>
      <title><![CDATA[Computability Part 6: Von Neumann Architecture]]></title>
      <description><![CDATA[<h1>Computability Part 6: Von Neumann Architecture</h1>

<p>During the previous posts, we covered <a href="https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html">Turing
machines</a>,
<a href="https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html">tag
systems</a>,
and <a href="https://vladris.com/blog/2022/06/11/computability-part-4-conway-s-game-of-life.html">cellular
automata</a>.
All of these are equivalent in terms of what they can compute, but some
are more practical than others. In this post, we'll look at the von
Neumann architecture of physical computers and implement an extremely
inefficient machine, write a few programs targeting it, then prove it is
Turing complete.</p>

<p>John von Neumann was a famous mathematician and physicist. Contemporary
with Alan Turing, he was aware of Turing's work on Turing machines and
computability. At the same time, von Neumann was involved in the
<a href="https://en.wikipedia.org/wiki/Manhattan_Project">Manhattan Project</a>
which required lots of computation provided by some early computers.
Thus he got involved in computer design. Unlike a Turing machine, a
physical computer can't have an infinite tape and while data is
processed based on input and states, this needs to be more ergonomic
than Yurii Rogozhin's 4-state 6-symbol machine we described in <a href="https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html">Part
2</a>.</p>

<blockquote>
<p>Von Neumann described a computer architecture as consisting of the
following components<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>:</p>

<ul>
<li>A <em>central arithmetic</em> component (CA) handling calculation.</li>
<li>A <em>central control</em> component (CC) driving which calculations
should be performed.</li>
<li><em>Memory</em> (M) for storage.</li>
<li><em>Input</em> (I) and <em>output</em> (O) components to get data into the
system and to communicate results outside of the system, from/to a
<em>recording medium</em> (R)</li>
</ul>
</blockquote>

<p>Here is a diagram of this architecture:</p>

<p><img src="https://vladris.com/blog/2022/07/31/vn.png" alt="image"/></p>

<p>Before von Neumann, computers were single-purpose devices - the
programming was hardwired. One of the major innovations, which might not
be apparent, is the introduction of a <em>central control</em> component and
the ability of the memory to store not only data but also the program
itself. This makes devices based on this architecture able to be
reprogrammed to perform different tasks.</p>

<p>We can now load an arbitrary program into memory. The program will use
the instructions which our <em>central arithmetic</em> understands to perform
computations. The <em>central control</em> can read this program and have the
<em>central arithmetic</em> perform the required operations. During execution,
data is also read from/written to memory.</p>

<p>Programs (and data) is loaded into memory through the <em>input</em> component
and results are sent through the <em>output</em> component.</p>

<p>While over the following decades this architecture got tweaked and
tuned, it's pretty obvious it is the ancestor of all modern computers:
computers still have CPUs, which include control and arithmetic, and
memory.</p>

<p>Let's create a virtual machine based on this architecture.</p>

<h2>Implementation</h2>

<p>We will create a very simple machine based on this architecture in
Python. In subsequent posts, we will look at other designs, but we're
starting with a direct translation of this architecture.</p>

<h3>Input</h3>

<p>The interface to our input component is a function that, when called,
returns an integer. This is all our machine needs to get data.</p>

<p>We will implement this over a text file. Our input component will buffer
this file into a list and expose a <code>read_one()</code> function that will
return one integer (as returned by [ord()]{.title-ref}) for each
character from the buffer.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">inp</span><span class="p">(</span><span class="n">file</span><span class="p">):</span>
    <span class="n">buffer</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
    <span class="k">return</span> <span class="k">lambda</span><span class="p">:</span> <span class="nb">ord</span><span class="p">(</span><span class="n">buffer</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>
</pre></div>

<h3>Output</h3>

<p>The interface to our output component is a function that takes an
integer as an argument. This is all our machine needs to output one
memory cell.</p>

<p>We will implement this using <code>print()</code> and actually convert the given
integer to a character. This is just to provide a convenient way for us
to look at output like <q>Hello world!</q>.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">out</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">value</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span>
</pre></div>

<h3>Memory</h3>

<p>Our memory will consist of a list of 10000 integers. We will
zero-initialize the list, then load a program from a file to memory,
starting at address 0. We expect the program to consist of a series of
integers separated by a space or a newline character. We'll use this
encoding to make it easier for us to peek at the code targeting our von
Neumann machine.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">memory</span><span class="p">(</span><span class="n">file</span><span class="p">):</span>
    <span class="n">memory</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">10000</span>
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">())</span><span class="o">.</span><span class="n">split</span><span class="p">()):</span>
        <span class="n">memory</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
</pre></div>

<p>10000 is chosen arbitrarily, at this point we're not worrying about
word size, page alignment etc. We simply have room to store 10000
integers in our memory, which will include both code and data.</p>

<h3>CPU</h3>

<p>We'll package the control and arithmetic components into a <code>CPU</code> class.
We'll initialize this class with memory, input, and output components.</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">CPU</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memory</span><span class="p">,</span> <span class="n">inp</span><span class="p">,</span> <span class="n">out</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">inp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">out</span> <span class="o">=</span> <span class="n">memory</span><span class="p">,</span> <span class="n">inp</span><span class="p">,</span> <span class="n">out</span>
</pre></div>

<h3>Central control</h3>

<p>Our control unit will maintain a <em>program counter</em> (<code>PC</code>), an index into
the memory pointing to the next instruction to execute. The machine runs
by reading 3 integers from memory (at <code>PC</code>, <code>PC + 1</code> and <code>PC + 2</code>), and
passing these to the arithmetic unit for processing. The program counter
is then incremented by 3. This repeats until <code>PC</code> goes outside the
bounds of the memory, at which point the machine halts (alternately we
could have provided some <code>HALT</code> instruction).</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
    <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">):</span>
        <span class="n">instr</span><span class="p">,</span> <span class="n">m1</span><span class="p">,</span> <span class="n">m2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">pc</span><span class="p">:</span><span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">instr</span><span class="p">,</span> <span class="n">m1</span><span class="p">,</span> <span class="n">m2</span><span class="p">)</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">+=</span> <span class="mi">3</span>
</pre></div>

<p>We will implement <code>process()</code> next.</p>

<h3>Central arithmetic</h3>

<p>Our arithmetic unit will process triples of
<code>&lt;Instruction&gt; &lt;memory address 1&gt; &lt;memory address 2&gt;</code>. It will support 8
instructions:</p>

<ul>
<li><code>AT</code> will set the value at <code>memory address 1</code> to be the value at the
memory address specified by the value at <code>memory address 2</code> (in
short, <code>m[m1] = m[m[m2]]</code>).</li>
<li><code>SET</code> will set the value at the memory address specified by the
value at <code>memory address 1</code> to be the value at <code>memory address 2</code>
(in short, <code>m[m[m1]] = m[2]</code>).</li>
<li><code>ADD</code> will update the value at <code>memory address 1</code> by adding the
value at <code>memory address 2</code> to it (in short, <code>m[m1] += m[m2]</code>).</li>
<li><code>NOT</code> will update the value at <code>memory address 1</code> to be 0 if the
value at <code>memory address 2</code> is different than 0, or 1 if the value
at <code>memory address 2</code> is 0 (in short, <code>m[m1] = !m[m2]</code>).</li>
<li><code>EQ</code> will compare the values at <code>memory address 1</code> and
<code>memory address 2</code> and update the value at <code>memory address 1</code> to be
1 if they are equal, 0 otherwise (in short,
<code>m[m1] = m[m1] == [m2]</code>).</li>
<li><code>JZ</code> will perform a conditional <em>jump</em> - if the value at
<code>memory address 1</code> is 0, it will update the program counter to point
to <code>memory address 2</code> (in short, <code>if !m[m1] then PC = m[m2]</code>).</li>
<li><code>INP</code> will read one integer from the input and store it at
<code>memory address 1</code> + an offset value specified at <code>memory address 2</code>
(in short, <code>m[m1 + m[m2]] = inp()</code>).</li>
<li><code>OUT</code> will write the value at <code>memory address 1</code> + an offset value
specified at <code>memory address 2</code> to the output (in short,
<code>out(m[m1 + m[m2]])</code>.</li>
</ul>

<p>Since the instructions are also read from memory, which is a list of
integers, we will encode them as integers: <code>AT = 0</code>, <code>SET = 1</code>, ...
<code>OUT = 7</code>.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instr</span><span class="p">,</span> <span class="n">m1</span><span class="p">,</span> <span class="n">m2</span><span class="p">):</span>
    <span class="k">match</span> <span class="n">instr</span><span class="p">:</span>
        <span class="k">case</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># AT</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]]</span>
        <span class="k">case</span> <span class="mi">1</span><span class="p">:</span> <span class="c1"># SET</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]</span>
        <span class="k">case</span> <span class="mi">2</span><span class="p">:</span> <span class="c1"># ADD</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]</span>
        <span class="k">case</span> <span class="mi">3</span><span class="p">:</span> <span class="c1"># NOT</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">=</span> <span class="o">+</span><span class="p">(</span><span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">])</span>
        <span class="k">case</span> <span class="mi">4</span><span class="p">:</span> <span class="c1"># EQ</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">=</span> <span class="o">+</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">])</span>
        <span class="k">case</span> <span class="mi">5</span><span class="p">:</span> <span class="c1"># JZ</span>
            <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]:</span>
                <span class="c1"># Set PC to m2 - 3 since run() will increment PC by 3</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">=</span> <span class="n">m2</span> <span class="o">-</span> <span class="mi">3</span>
        <span class="k">case</span> <span class="mi">6</span><span class="p">:</span> <span class="c1"># INP</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">inp</span><span class="p">()</span>
        <span class="k">case</span> <span class="mi">7</span><span class="p">:</span> <span class="c1"># OUT</span>
            <span class="n">out</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]])</span>
        <span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span> 
            <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">"Unknown instruction"</span><span class="p">)</span>
</pre></div>

<h3>Von Neumann VM</h3>

<p>Putting it all together, we'll take two input arguments: the first one
(<code>argv[1]</code>) will represent the code input file containing the program,
the second one (<code>argv[2]</code>) will be the file containing additional input
to be consumed by the <code>inp()</code> function:</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>

<span class="n">vn</span> <span class="o">=</span> <span class="n">CPU</span><span class="p">(</span><span class="n">memory</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="n">inp</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="n">out</span><span class="p">)</span>
<span class="n">vn</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>

<p>Here is our von Neumann virtual machine in one listing:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">inp</span><span class="p">(</span><span class="n">file</span><span class="p">):</span>
    <span class="n">buffer</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
    <span class="k">return</span> <span class="k">lambda</span><span class="p">:</span> <span class="nb">ord</span><span class="p">(</span><span class="n">buffer</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">))</span>

<span class="k">def</span><span class="w"> </span><span class="nf">out</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">value</span><span class="p">),</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span>

<span class="k">def</span><span class="w"> </span><span class="nf">memory</span><span class="p">(</span><span class="n">file</span><span class="p">):</span>
    <span class="n">memory</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="mi">10000</span>
    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="n">file</span><span class="p">)</span><span class="o">.</span><span class="n">readlines</span><span class="p">())</span><span class="o">.</span><span class="n">split</span><span class="p">()):</span>
        <span class="n">memory</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">memory</span>

<span class="k">class</span><span class="w"> </span><span class="nc">CPU</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">memory</span><span class="p">,</span> <span class="n">inp</span><span class="p">,</span> <span class="n">out</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">inp</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">out</span> <span class="o">=</span> <span class="n">memory</span><span class="p">,</span> <span class="n">inp</span><span class="p">,</span> <span class="n">out</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">):</span>
            <span class="n">instr</span><span class="p">,</span> <span class="n">m1</span><span class="p">,</span> <span class="n">m2</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">pc</span><span class="p">:</span><span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">process</span><span class="p">(</span><span class="n">instr</span><span class="p">,</span> <span class="n">m1</span><span class="p">,</span> <span class="n">m2</span><span class="p">)</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">+=</span> <span class="mi">3</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">process</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">instr</span><span class="p">,</span> <span class="n">m1</span><span class="p">,</span> <span class="n">m2</span><span class="p">):</span>
        <span class="k">match</span> <span class="n">instr</span><span class="p">:</span>
            <span class="k">case</span> <span class="mi">0</span><span class="p">:</span> <span class="c1"># AT</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]]</span>
            <span class="k">case</span> <span class="mi">1</span><span class="p">:</span> <span class="c1"># SET</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]</span>
            <span class="k">case</span> <span class="mi">2</span><span class="p">:</span> <span class="c1"># ADD</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">+=</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]</span>
            <span class="k">case</span> <span class="mi">3</span><span class="p">:</span> <span class="c1"># NOT</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">=</span> <span class="o">+</span><span class="p">(</span><span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">])</span>
            <span class="k">case</span> <span class="mi">4</span><span class="p">:</span> <span class="c1"># EQ</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">=</span> <span class="o">+</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">])</span>
            <span class="k">case</span> <span class="mi">5</span><span class="p">:</span> <span class="c1"># JZ</span>
                <span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span><span class="p">]:</span>
                    <span class="c1"># Set PC to m2 - 3 since run() will increment PC by 3</span>
                    <span class="bp">self</span><span class="o">.</span><span class="n">pc</span> <span class="o">=</span> <span class="n">m2</span> <span class="o">-</span> <span class="mi">3</span>
            <span class="k">case</span> <span class="mi">6</span><span class="p">:</span> <span class="c1"># INP</span>
                <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">inp</span><span class="p">()</span>
            <span class="k">case</span> <span class="mi">7</span><span class="p">:</span> <span class="c1"># OUT</span>
                <span class="n">out</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m1</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">memory</span><span class="p">[</span><span class="n">m2</span><span class="p">]])</span>
            <span class="k">case</span><span class="w"> </span><span class="k">_</span><span class="p">:</span> 
                <span class="k">raise</span> <span class="ne">Exception</span><span class="p">(</span><span class="s2">"Unknown instruction"</span><span class="p">)</span>

<span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>

<span class="n">vn</span> <span class="o">=</span> <span class="n">CPU</span><span class="p">(</span><span class="n">memory</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]),</span> <span class="n">inp</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]),</span> <span class="n">out</span><span class="p">)</span>
<span class="n">vn</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>

<p>We can save this as <code>vn.py</code>.</p>

<p>Let's create a <q>Hello world!</q> program targeting this machine. We will
use the <code>OUT</code> instruction to output each character of <q>Hello</q> and a
new line (<code>\n</code>). We'll first tell the VM to output the values at memory
address 21 to 26:</p>
<div class="highlight"><pre><span/>7 21 9999
7 22 9999
7 23 9999
7 24 9999
7 25 9999
7 26 9999
</pre></div>

<p>We are referencing addresses 21 to 26 plus the offset 0 (the value at
memory <code>9999</code>, since our memory is initialized with zeros).</p>

<p>We want to halt after this, so we need to jump our program counter to
10000. We will do this by using our <code>JZ</code> instruction, saying <em>if the
memory value at index 9999 is 0, jump to 10000</em>:</p>
<div class="highlight"><pre><span/>5 9999 10000
</pre></div>

<p>Now we get to memory address 21, so we will set the values of memory 21
to 26 to the values of the characters in <q>Hello</q> (as returned by
<code>ord()</code>) plus a <code>10</code> for <code>\n</code>:</p>
<div class="highlight"><pre><span/>72 101 108 108 111 10
</pre></div>

<p>Here is the full listing which we can save as <code>hello.vn</code>:</p>
<div class="highlight"><pre><span/>7 21 9999
7 22 9999
7 23 9999
7 24 9999
7 25 9999
7 26 9999
5 9999 10000
72 101 108 108 111 10
</pre></div>

<p>We can then use our VM to run the program like this:</p>
<div class="highlight"><pre><span/>touch<span class="w"> </span>input
python3<span class="w"> </span>vn.py<span class="w"> </span>hello.vn<span class="w"> </span>input
</pre></div>

<p>We're also creating a blank <code>input</code> file since <q>Hello world!</q> isn't
going to read anything via <code>inp()</code>.</p>

<p>Running this should print <code>Hello</code>. Our <q>program</q> is pretty hard to
write or read, we're programming with integers. Let's make our life a
bit easier.</p>

<h2>Assembler</h2>

<p>We will implement an assembler for our VM. An assembly language is a
low-level language closely matching the architecture it targets (in our
case, our very simple von Neumann machine).</p>

<p>Our assembler will take 2 arguments - an input file and an output file -
and automatically translate the input (assembly language) into
instructions for our VM.</p>

<p>We will add the following features:</p>

<ul>
<li>Comments - Lines starting with <code>#</code> will be ignored.</li>
<li>Instructions - We will express our instructions as <code>at</code>, <code>set</code>,
<code>add</code>, <code>not</code>, <code>eq</code>, <code>jz</code>, <code>inp</code>, <code>out</code> to represent the instructions
<code>0</code>, <code>1</code>, ... <code>5</code>.</li>
<li>Labels - We will tag a location in the code by a string ending in
<code>:</code>, for example <code>HERE:</code>. We will then be able to refer to the
location using the identified preceded by <code>:</code>, like <code>:HERE</code>. We will
also allow adding an offset to a reference: <code>:HERE+2</code> is 2 past the
<code>HERE</code> label.</li>
<li><code>ORD</code> macro - To make implementing <q>Hello world!</q> easier, we will
provide the <code>ORD()</code> macro which will return the integer
representation of the character passed to it, for example <code>ORD(H)</code>
will return <code>72</code>.</li>
</ul>

<p>Using this assembly language, we can rewrite <q>Hello world!</q> as:</p>
<div class="highlight"><pre><span/>## Print 6 characters starting from DATA
out :DATA 9999
out :DATA+1 9999
out :DATA+2 9999
out :DATA+3 9999
out :DATA+4 9999
out :DATA+5 9999

## End program
jz 9999 10000

## Data section
DATA: ORD(H) ORD(e) ORD(l) ORD(l) ORD(o) 10
</pre></div>

<p>First, we'll read the input file and convert it into a list of tokens.
We will ignore lines starting with <code>#</code> (so we can add comments to our
assembly file).</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>

<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Usage: asm.py &lt;input&gt; &lt;output&gt;"</span><span class="p">)</span>
    <span class="n">exit</span><span class="p">()</span>

<span class="c1">## Read all lines into a list</span>
<span class="n">lines</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span>
<span class="c1">## Filter out blank lines and lines starting with '#'</span>
<span class="n">lines</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">line</span><span class="p">:</span> <span class="n">line</span> <span class="ow">and</span> <span class="n">line</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'#'</span><span class="p">,</span> <span class="n">lines</span><span class="p">))</span>
<span class="c1">## Join all lines and split into tokens</span>
<span class="n">tokens</span> <span class="o">=</span> <span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
</pre></div>

<p>The labels themselves aren't part of the program, rather mark locations
in the program, so in the next step we will pluck these out from the
list of tokens but retain the index they are referencing:</p>
<div class="highlight"><pre><span/><span class="c1">## pluck labels and remember position</span>
<span class="n">labels</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="p">{},</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
    <span class="c1"># If not a label, advance</span>
    <span class="k">if</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">':'</span><span class="p">:</span>
        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">continue</span>

    <span class="c1"># Store location and pluck label</span>
    <span class="n">labels</span><span class="p">[</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">][:</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="n">i</span>
    <span class="n">tokens</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</pre></div>

<p>Now we will process all tokens and handle the following cases:</p>

<ul>
<li>If token starts with <code>:</code>, it is a label reference, so replace it
with the actual location (as stored during the previous step).</li>
<li>If the token is an op code, replace it with the integer value of the
op code.</li>
<li>If the token is an <code>ORD()</code> macro, replace the character passed to
<code>ORD()</code> with its value.</li>
</ul>
<div class="highlight"><pre><span/><span class="c1">## Op code list (constant)</span>
<span class="n">OP_CODES</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'at'</span><span class="p">,</span> <span class="s1">'set'</span><span class="p">,</span> <span class="s1">'add'</span><span class="p">,</span> <span class="s1">'not'</span><span class="p">,</span> <span class="s1">'eq'</span><span class="p">,</span> <span class="s1">'jz'</span><span class="p">,</span> <span class="s1">'inp'</span><span class="p">,</span> <span class="s1">'out'</span><span class="p">]</span>

<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">token</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
    <span class="c1"># replace label references with actual position</span>
    <span class="k">if</span> <span class="n">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">':'</span><span class="p">:</span>
        <span class="k">if</span> <span class="s1">'+'</span> <span class="ow">in</span> <span class="n">token</span><span class="p">:</span>
            <span class="n">base</span><span class="p">,</span> <span class="n">offset</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'+'</span><span class="p">)</span>
            <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">labels</span><span class="p">[</span><span class="n">base</span><span class="p">[</span><span class="mi">1</span><span class="p">:]]</span> <span class="o">+</span> <span class="nb">int</span><span class="p">(</span><span class="n">offset</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">labels</span><span class="p">[</span><span class="n">token</span><span class="p">[</span><span class="mi">1</span><span class="p">:]]</span>

    <span class="c1"># replace op codes with values</span>
    <span class="k">if</span> <span class="n">token</span> <span class="ow">in</span> <span class="n">OP_CODES</span><span class="p">:</span>
        <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">OP_CODES</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">token</span><span class="p">)</span>

    <span class="c1"># replace ORD macro</span>
    <span class="k">if</span> <span class="n">token</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'ORD('</span><span class="p">:</span>
        <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="n">token</span><span class="p">[</span><span class="mi">4</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
</pre></div>

<p>Finally, we write all tokens to the output file:</p>
<div class="highlight"><pre><span/><span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="s2">"w"</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span>
    <span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">token</span><span class="p">)</span> <span class="k">for</span> <span class="n">token</span> <span class="ow">in</span> <span class="n">tokens</span><span class="p">]))</span>
</pre></div>

<p>Here is the full source code of our assembler (<code>asm.py</code>):</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>

<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">3</span><span class="p">:</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"Usage: asm.py &lt;input&gt; &lt;output&gt;"</span><span class="p">)</span>
    <span class="n">exit</span><span class="p">()</span>

<span class="c1">## Read all lines into a list</span>
<span class="n">lines</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span><span class="o">.</span><span class="n">readlines</span><span class="p">()</span>
<span class="c1">## Filter out blank lines and lines starting with '#'</span>
<span class="n">lines</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="k">lambda</span> <span class="n">line</span><span class="p">:</span> <span class="n">line</span> <span class="ow">and</span> <span class="n">line</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">'#'</span><span class="p">,</span> <span class="n">lines</span><span class="p">))</span>
<span class="c1">## Join all lines and split into tokens</span>
<span class="n">tokens</span> <span class="o">=</span> <span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>

<span class="c1">## pluck labels and remember position</span>
<span class="n">labels</span><span class="p">,</span> <span class="n">i</span> <span class="o">=</span> <span class="p">{},</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
    <span class="c1"># If not a label, advance</span>
    <span class="k">if</span> <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="s1">':'</span><span class="p">:</span>
        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">continue</span>

    <span class="c1"># Store location and pluck label</span>
    <span class="n">labels</span><span class="p">[</span><span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">][:</span><span class="o">-</span><span class="mi">1</span><span class="p">]]</span> <span class="o">=</span> <span class="n">i</span>
    <span class="n">tokens</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>

<span class="c1">## Op code list (constant)</span>
<span class="n">OP_CODES</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'at'</span><span class="p">,</span> <span class="s1">'set'</span><span class="p">,</span> <span class="s1">'add'</span><span class="p">,</span> <span class="s1">'not'</span><span class="p">,</span> <span class="s1">'eq'</span><span class="p">,</span> <span class="s1">'jz'</span><span class="p">,</span> <span class="s1">'inp'</span><span class="p">,</span> <span class="s1">'out'</span><span class="p">]</span>

<span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="n">token</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">tokens</span><span class="p">):</span>
    <span class="c1"># replace label references with actual position</span>
    <span class="k">if</span> <span class="n">token</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">':'</span><span class="p">:</span>
        <span class="k">if</span> <span class="s1">'+'</span> <span class="ow">in</span> <span class="n">token</span><span class="p">:</span>
            <span class="n">base</span><span class="p">,</span> <span class="n">offset</span> <span class="o">=</span> <span class="n">token</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'+'</span><span class="p">)</span>
            <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">labels</span><span class="p">[</span><span class="n">base</span><span class="p">[</span><span class="mi">1</span><span class="p">:]]</span> <span class="o">+</span> <span class="nb">int</span><span class="p">(</span><span class="n">offset</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">labels</span><span class="p">[</span><span class="n">token</span><span class="p">[</span><span class="mi">1</span><span class="p">:]]</span>

    <span class="c1"># replace op codes with values</span>
    <span class="k">if</span> <span class="n">token</span> <span class="ow">in</span> <span class="n">OP_CODES</span><span class="p">:</span>
        <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">OP_CODES</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="n">token</span><span class="p">)</span>

    <span class="c1"># replace ORD macro</span>
    <span class="k">if</span> <span class="n">token</span><span class="p">[:</span><span class="mi">4</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'ORD('</span><span class="p">:</span>
        <span class="n">tokens</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="n">token</span><span class="p">[</span><span class="mi">4</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>

<span class="nb">open</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="s2">"w"</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span>
    <span class="s1">' '</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">token</span><span class="p">)</span> <span class="k">for</span> <span class="n">token</span> <span class="ow">in</span> <span class="n">tokens</span><span class="p">]))</span>
</pre></div>

<p>We can now save our assembly <q>Hello world!</q> (listed above) to a file,
let's call it <code>hello.asm</code> and use the assembler to convert it to a
program our VM can execute:</p>
<div class="highlight"><pre><span/>python3<span class="w"> </span>asm.py<span class="w"> </span>hello.asm<span class="w"> </span>hello.vn
</pre></div>

<p>The resulting <code>hello.vn</code> should have the same content as our
hand-crafted <q>Hello world!</q>, minus the newlines (the assembler
doesn't output newlines). The content of the assembled file <code>hello.vn</code>
is:</p>
<div class="highlight"><pre><span/>7 21 9999 7 22 9999 7 23 9999 7 24 9999 7 25 9999 7 26 9999 5 9999 10000 72 101 108 108 111 10
</pre></div>

<p>We can run this using:</p>
<div class="highlight"><pre><span/>python3<span class="w"> </span>vn.py<span class="w"> </span>hello.vn<span class="w"> </span>input
</pre></div>

<p>We are again using an empty input file since we don't need input. As a
convention, we use the <code>.asm</code> extensions for assembly files and <code>.vn</code>
for assembled files targeting the VM.</p>

<h3>Variables and loops</h3>

<p>Let's rewrite our program: instead of outputting <code>:DATA</code>, then
<code>:DATA+1</code>, then <code>DATA+2</code>... we should be able to output <code>:DATA + :I</code>
where <code>:I</code> goes from 0 to 5.</p>

<p>We can easily use a variable by tagging any part of the program then
referencing it, then using that label to refer to the variable.</p>
<div class="highlight"><pre><span/>I: 0
</pre></div>

<p>Then we can use <code>:I</code> to reference to it. We will use a <code>COUNTER</code>
variable to count down from 6 to 0, and an offset variable <code>I</code>:</p>
<div class="highlight"><pre><span/>## Variables
I: 0
COUNTER: 6
</pre></div>

<p>We also need a couple of constant values: <code>0</code>, <code>1</code> - by which we
increment <code>I</code> during each iteration, and <code>-1</code> to decrement <code>COUNTER</code>
during each iteration. And, of course, our <code>DATA</code>, where we store the
<q>Hello</q> string:</p>
<div class="highlight"><pre><span/>## Constants
CONST: 0 1 -1

## Data
DATA: ORD(H) ORD(e) ORD(l) ORD(l) ORD(o) 10
</pre></div>

<p>Now lets look at how we can implement a loop using <code>JZ</code>:</p>
<div class="highlight"><pre><span/>## Beginning of loop
LOOP: 
## Output I
out :DATA :I
## Decrement COUNTER, increment I
add :COUNTER :CONST+2
add :I :CONST+1
## If COUNTER is 0, we're done
jz :COUNTER 10000
## If not, jump to the start of the loop
jz :CONST :LOOP
</pre></div>

<p>At each iteration, our loop will output the character value at <code>DATA</code>
plus the offset specified in <code>I</code> (initially 0). Then we subtract -1 from
our <code>COUNTER</code> and add 1 to <code>I</code>. Since our VM uses memory addresses for
all operations, we stored <code>1</code> and <code>-1</code> in memory at <code>CONST</code> and
<code>CONST+1</code> respectively.</p>

<p>If <code>COUNTER</code> is 0, we're done, so we jump to <code>10000</code>. If not, we repeat
the loop (jump to <code>LOOP</code> if <code>CONST</code> is 0, but <code>CONST</code> is always 0).</p>

<p>Here is the full listing of this program:</p>
<div class="highlight"><pre><span/>## Beginning of loop
LOOP: 
## Output I
out :DATA :I
## Decrement COUNTER, increment I
add :COUNTER :CONST+2
add :I :CONST+1
## If COUNTER is 0, we're done
jz :COUNTER 10000
## If not, jump to the start of the loop
jz :CONST :LOOP

## Constants
CONST: 0 1 -1

## Data
DATA: ORD(H) ORD(e) ORD(l) ORD(l) ORD(o) 10

## Variables
I: 0
COUNTER: 6
</pre></div>

<p>We can save this as <code>hello2.asm</code>, then assemble and run it:</p>
<div class="highlight"><pre><span/>python3<span class="w"> </span>asm.py<span class="w"> </span>hello2.asm<span class="w"> </span>hello2.vn
python3<span class="w"> </span>vn.py<span class="w"> </span>hello2.vn
</pre></div>

<h3>Notes</h3>

<p>A few notes: data is mixed with code in all our programs, which follows
from the von Neumann architecture, in which the memory of the system
stores both code and data. This is fundamentally true for all computers,
and enables some interesting behavior like self-modifying code. This
could be intentional, or we could, accidentally due to a bug, interpret
data as code or vice-versa, code as data. Modern systems employ various
additional protections to prevent this type of accidental usage.</p>

<p>Because our particular VM starts execution from memory location 0, we
have to place our constants and variables (data) after the instructions
in the program. Executable files on modern systems similarly contain
code and data segments, albeit with more complex layout and rules.</p>

<h2>Turing-completeness</h2>

<p>Let's prove our simple von Neumann VM is Turing-complete, meaning
capable of universal computation. As we saw throughout this series of
blog posts, the best way to prove this is to emulate another known
Turing-complete system.</p>

<p>We will prove this by implementing a
<a href="https://en.wikipedia.org/wiki/Brainfuck">Brainfuck</a> interpreter. We
covered Brainfuck during the <a href="https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html">second post in the
series</a>,
under <em>Esoteric Turing machines</em>. To recap: Brainfuck (BF) uses a byte
array (tape), a data pointer (index in the array), and 8 symbols: <code>&gt;</code>,
<code>&lt;</code>, <code>+</code>, <code>-</code>, <code>.</code>, <code>,</code>, <code>[</code>, <code>]</code>. The symbols are interpreted as:</p>

<ul>
<li><code>&gt;</code>: Increment the data pointer (move head right).</li>
<li><code>&lt;</code>: Decrement the data pointer (move head left).</li>
<li><code>+</code>: Increment array value at data pointer.</li>
<li><code>-</code>: Decrement array value at data pointer.</li>
<li><code>.</code>: Output value at data pointer.</li>
<li><code>,</code>: Read 1 byte of input and store at data pointer.</li>
<li><code>[</code>: If the byte at data pointer is 0, jump right to the matching
<code>]</code>, else increment data pointer.</li>
<li><code>]</code>: If the byte at data pointer is not 0, jump left to the matching
<code>[</code>, else decrement data pointer.</li>
</ul>

<p>We will use our assembly language to implement a program which reads a
BF program from input, then executes it. Effectively, we'll use our
very simple virtual machine to emulate another very simple virtual
machine!</p>

<p>I won't cover the details of the implementation, since it is quite
cumbersome due to the simplicity of our VM and assembly language. I will
just provide a short summary of what is going on:</p>

<ul>
<li>We'll start by reading the BF program from input, until we
encounter a newline (<code>\</code>).</li>
<li>We will use a <code>CODE_PTR</code> code pointer variable to point to the
current BF instructions and a <code>DATA_PTR</code> data pointer variable to
point to the BF array.</li>
<li>We'll overlay the BF array BF array over the VM memory, starting at
address 5000 (middle of our memory).</li>
<li>We will then handle each possible input (<code>&gt;</code>, <code>&lt;</code>, etc.).</li>
<li>Most of the instructions are easy to implement, the most complex are
<code>[</code> and <code>]</code>, which require keeping track of unbalanced parenthesis
so we properly jump from <code>[</code> to matching <code>]</code> and vice-versa.</li>
</ul>

<p>Here is the full Brainfuck interpreter implemented in our assembly
language:</p>
<div class="highlight"><pre><span/>## Read Brainfuck program until a \n is encountered
START:
## Read one integer at PROG + offset I
inp :PROG :I
## Increment I by 1
add :I :CONST+1
## Zero out DONE_READING (!1)
not :DONE_READING :CONST+1
## DONE_READING = 10
add :DONE_READING :CONST+3
## Load the last integer we read in TEMP
at :TEMP :END
## Increment END to keep track of program end
add :END :CONST+1
## Check if the last integer we read was 10 (\n)
eq :DONE_READING :TEMP
## If it wasn't zero, jump to start and read another value
jz :DONE_READING :START 

## Start running program
BF_RUN:
at :TEMP :CODE_PTR
add :CODE_PTR :CONST+1

## Check if we're on a &gt; instruction
not :TEMP2 :CONST+1
add :TEMP2 :BF
eq :TEMP2 :TEMP
not :TEMP2 :TEMP2
jz :TEMP2 :RIGHT

## Check if we're on a &lt; instruction
not :TEMP2 :CONST+1
add :TEMP2 :BF+1
eq :TEMP2 :TEMP
not :TEMP2 :TEMP2
jz :TEMP2 :LEFT

## Check if we're on a + instruction
not :TEMP2 :CONST+1
add :TEMP2 :BF+2
eq :TEMP2 :TEMP
not :TEMP2 :TEMP2
jz :TEMP2 :INC

## Check if we're on a - instruction
not :TEMP2 :CONST+1
add :TEMP2 :BF+3
eq :TEMP2 :TEMP
not :TEMP2 :TEMP2
jz :TEMP2 :DEC

## Check if we're on a . instruction
not :TEMP2 :CONST+1
add :TEMP2 :BF+4
eq :TEMP2 :TEMP
not :TEMP2 :TEMP2
jz :TEMP2 :OUT

## Check if we're on a , instruction
not :TEMP2 :CONST+1
add :TEMP2 :BF+5
eq :TEMP2 :TEMP
not :TEMP2 :TEMP2
jz :TEMP2 :IN

## Check if we're on a [ instruction
not :TEMP2 :CONST+1
add :TEMP2 :BF+6
eq :TEMP2 :TEMP
not :TEMP2 :TEMP2
jz :TEMP2 :FORWARD

## Check if we're on a ] instruction
not :TEMP2 :CONST+1
add :TEMP2 :BF+7
eq :TEMP2 :TEMP
not :TEMP2 :TEMP2
jz :TEMP2 :BACKWARD

## No matching BF instruction so we're done
jz :CONST 10000

RIGHT:
## &gt; - increment data pointer
add :DATA_PTR :CONST+1
jz :CONST :BF_RUN

LEFT:
## &lt; - decrement data pointer
add :DATA_PTR :CONST+2
jz :CONST :BF_RUN

INC:
## + - increment cell
at :TEMP :DATA_PTR
add :TEMP :CONST+1
set :DATA_PTR :TEMP
jz :CONST :BF_RUN

DEC:
## - - decrement cell
at :TEMP :DATA_PTR
add :TEMP :CONST+2
set :DATA_PTR :TEMP
jz :CONST :BF_RUN

OUT:
## . - output cell
at :TEMP :DATA_PTR
out :TEMP :CONST
jz :CONST :BF_RUN

IN:
## , - store input in cell
inp :TEMP :CONST
set :DATA_PTR :TEMP
jz :CONST :BF_RUN

FORWARD:
## [
at :TEMP :DATA_PTR    
not :TEMP :TEMP
## If value in cell is not 0, continue
jz :TEMP :BF_RUN
## Find matching ]
## Set TEMP to 1, counting unbalanced [
not :TEMP :TEMP
add :TEMP :CONST+1
SCAN_FORWARD:
at :TEMP2 :CODE_PTR
eq :TEMP2 :BF+6
not :TEMP2 :TEMP2
## Jump if found a [
jz :TEMP2 :FORWARD_LPAR
at :TEMP2 :CODE_PTR
eq :TEMP2 :BF+7
not :TEMP2 :TEMP2
## Jump if found a ]
jz :TEMP2 :FORWARD_RPAR
## Keep scanning
add :CODE_PTR :CONST+1
jz :CONST :SCAN_FORWARD
## Increment counter when finding a [
FORWARD_LPAR:
add :TEMP :CONST+1
add :CODE_PTR :CONST+1
jz :CONST :SCAN_FORWARD
## Decrement counter when finding a ]
FORWARD_RPAR:
add :TEMP :CONST+2
## If counter is 0, we're done
jz :TEMP :BF_RUN
## Else keep scanning
add :CODE_PTR :CONST+1
jz :CONST :SCAN_FORWARD

BACKWARD:
## ]
at :TEMP :DATA_PTR    
## If value in cell is 0, continue
jz :TEMP :BF_RUN
## Find matching [
## Set TEMP to 1, counting unbalanced ]
not :TEMP :TEMP
add :TEMP :CONST+1
## Move code pointer back 2
add :CODE_PTR :CONST+2
add :CODE_PTR :CONST+2
SCAN_BACKWARD:
at :TEMP2 :CODE_PTR
eq :TEMP2 :BF+6
not :TEMP2 :TEMP2
## Jump if found a [
jz :TEMP2 :BACKWARD_LPAR
at :TEMP2 :CODE_PTR
eq :TEMP2 :BF+7
not :TEMP2 :TEMP2
## Jump if found a ]
jz :TEMP2 :BACKWARD_RPAR
## Keep scanning
add :CODE_PTR :CONST+2
jz :CONST :SCAN_BACKWARD
## Decrement counter when finding a [
BACKWARD_LPAR:
add :TEMP :CONST+2
## If counter is 0, we're done
jz :TEMP :BF_RUN
## Else keep scanning
add :CODE_PTR :CONST+2
jz :CONST :SCAN_BACKWARD
## Increment counter when finding a ]
BACKWARD_RPAR:
add :TEMP :CONST+1
add :CODE_PTR :CONST+2
jz :CONST :SCAN_BACKWARD

CONST: 0 1 -1 10 
BF: ORD(&gt;) ORD(&lt;) ORD(+) ORD(-) ORD(.) ORD(,) ORD([) ORD(])
I: 0
TEMP: 0
TEMP2: 0
END: :PROG
DONE_READING: 0
CODE_PTR: :PROG
DATA_PTR: 5000

## We'll load the BF program here
PROG:
</pre></div>

<p>We can save this program as <code>bf.asm</code>. We will also create a Brainfuck
program to run - <q>Hello world</q>:</p>
<div class="highlight"><pre><span/>++++++++[&gt;++++[&gt;++&gt;+++&gt;+++&gt;+&lt;&lt;&lt;&lt;-]&gt;+&gt;+&gt;-&gt;&gt;+[&lt;]&lt;-]&gt;&gt;.&gt;---.+++++++..+++.&gt;&gt;.&lt;-.&lt;.+++.------.--------.&gt;&gt;+.&gt;++.
</pre></div>

<p>We will save this as <code>hello.bf</code>. Now we can compile our BF interpreter
and run it using our VM:</p>
<div class="highlight"><pre><span/>python3<span class="w"> </span>asm.py<span class="w"> </span>bf.asm<span class="w"> </span>bf.vn
python3<span class="w"> </span>vn.py<span class="w"> </span>bf.vn<span class="w"> </span>hello.bf
</pre></div>

<p>This should output <q>Hello world!</q>.</p>

<p>Since Brainfuck is Turing-complete and our VM can emulate a Brainfuck
interpreter, our VM is also Turing-complete.</p>

<h2>Summary</h2>

<ul>
<li>We talked about the von Neumann architecture and looked at a simple
VM built using this architecture.</li>
<li>We created an assembler targeting this VM, to make it easier to
write code that runs on the VM.</li>
<li>We looked at a couple of versions of <q>Hello world</q>, and saw how we
can use variables and loops.</li>
<li>Finally, we implemented a Brainfuck interpreter that runs on the VM,
proving our von Neumann machine is Turing-complete.</li>
</ul>

<p>For convenience, the code we covered in this post is online here:</p>

<ul>
<li><a href="https://vladris.com/code/vonNeumann/vn.py">vn.py</a> - virtual
machine.</li>
<li><a href="https://vladris.com/code/vonNeumann/asm.py">asm.py</a> - assembler.</li>
<li><a href="https://vladris.com/code/vonNeumann/hello.asm">hello.asm</a> - simple
<q>Hello world</q>.</li>
<li><a href="https://vladris.com/code/vonNeumann/hello2.asm">hello2.asm</a> -
<q>Hello world</q> using a loop.</li>
<li><a href="https://vladris.com/code/vonNeumann/bf.asm">bf.asm</a> - Brainfuck
interpreter.</li>
<li><a href="https://vladris.com/code/vonNeumann/hello.bf">hello.bf</a> - <q>Hello
world</q> in Brainfuck.</li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p><a href="https://web.archive.org/web/20130314123032/http://qss.stanford.edu/%7Egodfrey/vonNeumann/vnedvac.pdf">First Draft of a Report on the
EDVAC</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sun, 31 Jul 2022 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/07/06/computability-part-5-elementary-cellular-automata.html</link>
      <guid>https://vladris.com/blog/2022/07/06/computability-part-5-elementary-cellular-automata.html</guid>
      <title><![CDATA[Computability Part 5: Elementary Cellular Automata]]></title>
      <description><![CDATA[<h1>Computability Part 5: Elementary Cellular Automata</h1>

<p>In the <a href="https://vladris.com/blog/2022/06/11/computability-part-4-conway-s-game-of-life.html">previous
post</a>
we talked about Conway's Game of Life as a well-known cellular
automaton. In this post we will cover even simpler automata - the
<em>elementary cellular automata</em>. Stephen Wolfram covers them extensively
in his book, <a href="https://www.wolframscience.com/">A New Kind of Science</a>.</p>

<p>To recap, we defined a cellular automaton as a discrete n-dimensional
lattice of cells, a set of states (for each cell), a notion of
neighborhood for each cell, and a transition function mapping the
neighborhood of each cell to a new cell state.</p>

<p>An elementary cellular automaton is 1-dimensional - an array of cells. A
cell can be either <em>on</em> or <em>off</em> (just like in Conway's Game of Life).
The neighborhood of a cell, meaning the cells that we take into account
when we determine the next state of the next generation, consists of the
cell itself and its left and right neighbors.</p>

<p>For example, we can define an elementary cellular automaton with the
following rules:</p>
<div class="highlight"><pre><span/>[ on,  on,  on] -&gt; off
[ on,  on, off] -&gt; off
[ on, off,  on] -&gt; off
[ on, off, off] -&gt;  on
[off,  on,  on] -&gt; off
[off,  on, off] -&gt;  on
[off, off,  on] -&gt;  on
[off, off, off] -&gt; off
</pre></div>

<p>If we start with a single <em>on</em> cell and produce 10 generations, we get
(using <code>#</code> to mean <em>on</em>):</p>
<div class="highlight"><pre><span/>#
###
#   #
### ###
#       #
###     ###
#   #   #   #
### ### ### ###
#               #
###             ###
</pre></div>

<h2>Rule encoding</h2>

<p>The elementary cellular automata can easily be enumerated exhaustively:
the neighborhood of a cell can be in only one of 8 states, as we saw
above: <code>[on, on, on]</code>, <code>[on, on, off]</code>, ... <code>[off, off, off]</code>. The
transition function maps each of these possible states to either <em>on</em> or
<em>off</em>. If we think of the <em>on</em>/<em>off</em> as a bit, we need 8 bits to
represent the transition function.</p>
<div class="highlight"><pre><span/>[ on,  on,  on] -&gt; off
[ on,  on, off] -&gt; off
[ on, off,  on] -&gt; off
[ on, off, off] -&gt;  on
[off,  on,  on] -&gt; off
[off,  on, off] -&gt;  on
[off, off,  on] -&gt;  on
[off, off, off] -&gt; off
</pre></div>

<p>can be represented as the binary number <code>00010110</code>, which, in decimal,
is 22 (where <code>[off, off, off]</code> is the least significant bit). We can
represent numbers from 0 to 255 in 8 bits, so there are exactly 256
elementary cellular automata. This encoding is referred to as <em>Rule</em> as
in <q>transition rule</q>. The elementary cellular automata in our above
example is called <em>Rule 22</em> .</p>

<h2>Elementary cellular automata behavior</h2>

<p>A common way to plot the evolution of an elementary cellular automata
over multiple generation is to render each generation below the previous
one, like our above example using <code>#</code> for <em>on</em>. A more condensed version
with 1 pixel per cell of running rule 22 for 301 generations looks like
this:</p>

<p><img src="https://vladris.com/blog/2022/07/06/22.png" alt="image"/></p>

<p>At this level, we can clearly see patterns emerging in the automaton. We
get an even more interesting view if, instead of starting with just a
single <em>on</em> cell, we start with a random state - an array of random <em>on</em>
and <em>off</em> cells. Here is rule 22 starting with 301 random cells and
running for 301 generations:</p>

<p><img src="https://vladris.com/blog/2022/07/06/22r.png" alt="image"/></p>

<p>We can also easily see some of the automatons are complements of other
automatons: if we simply flip each bit, we end up with a complementary
version. Rule 22's complement is Rule 151:</p>

<p><img src="https://vladris.com/blog/2022/07/06/151r.png" alt="image"/></p>

<p>We can also reflect a rule by swapping the transitions for
<code>[on, off, off]</code> with <code>[off, off, on]</code> and <code>[on, on, off]</code> with
<code>[off, on, on]</code>. This doesn't work for rule 22, since its reflection is
still 22, but, for example, rules 3 and 17 are reflections of each
other.</p>

<p>Rule 3:</p>
<div class="highlight"><pre><span/>[ on,  on,  on] -&gt; off
[ on,  on, off] -&gt; off
[ on, off,  on] -&gt; off
[ on, off, off] -&gt; off
[off,  on,  on] -&gt; off
[off,  on, off] -&gt; off
[off, off,  on] -&gt;  on
[off, off, off] -&gt;  on
</pre></div>

<p>Renders as:</p>

<p><img src="https://vladris.com/blog/2022/07/06/3.png" alt="image"/></p>

<p>Rule 17:</p>
<div class="highlight"><pre><span/>[ on,  on,  on] -&gt; off
[ on,  on, off] -&gt; off
[ on, off,  on] -&gt; off
[ on, off, off] -&gt;  on
[off,  on,  on] -&gt; off
[off,  on, off] -&gt; off
[off, off,  on] -&gt; off
[off, off, off] -&gt;  on
</pre></div>

<p>Renders as:</p>

<p><img src="https://vladris.com/blog/2022/07/06/17.png" alt="image"/></p>

<p>That means that, even though there are 256 possible automata, from
behavioral perspective, some are complements or reflections of others
thus exhibit the same behavior. In fact, there are only 88 uniquely
behaving automata, all others being complements and/or reflections of
these.</p>

<h2>Implementation</h2>

<p>Let's look at a Python implementation. We will represent the state of
an automaton as a list of Boolean cells. We can encode the state of a
neighborhood as a 3 bit number:
<code>left neighbor * 4 + cell * 2 + right neighbor</code>. Given a list of cells
and the index of a cell, we have:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">neighbors</span><span class="p">(</span><span class="n">cells</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">cells</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">else</span> <span class="kc">False</span><span class="p">)</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">+</span> \
        <span class="n">cells</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> \
        <span class="p">(</span><span class="n">cells</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">cells</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="kc">False</span><span class="p">)</span>
</pre></div>

<p>If we run off the ends of the list, we assume the state of that cell is
<em>off</em>. In Python, <code>False</code> becomes <code>0</code> and <code>True</code> becomes 1 if we do
arithmetic with them, so this function will return a number between 0
and 7.</p>

<p>We can derive the transitions from the rule number by taking a rule
number and expanding it into a dictionary that maps each value from 0 to
7 to the corresponding bit in the rule number value:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">transition</span><span class="p">(</span><span class="n">rule</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">{</span><span class="n">i</span><span class="p">:</span> <span class="n">rule</span> <span class="o">&amp;</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">)}</span>
</pre></div>

<p>This might be a bit hard to understand, so let's work through an
example. Let's take Rule 22. The binary representation of Rule 22 is
<code>00010110</code>. We're iterating over the range 0...7 (<code>i</code>) and for each of
these values, we shift <code>1</code> exactly <code>i</code> bits left. Then we check if the
rule <em>logic AND</em> this shifted bit is different than 0.</p>

<p>For <code>i == 0</code>: <code>00010110 &amp; (1 &lt;&lt; 0)</code>, which is <code>00010110 &amp; 00000001</code>, we
get <code>False</code>, so <code>transitions[0] = False</code>.</p>

<p>For <code>i == 1</code>: <code>00010110 &amp; (1 &lt;&lt; 1)</code>, which is <code>00010110 &amp; 00000010</code>, we
get <code>True</code>, so <code>transitions[1] = True</code>.</p>

<p>...</p>

<p>For <code>i == 7</code>: <code>00010110 &amp; (1 &lt;&lt; 7)</code>, which is <code>00010110 &amp; 10000000</code>, we
get <code>False</code>, so <code>transitions[7] = False</code>.</p>

<p>Remember the keys of the dictionary are neighborhood states.</p>

<p>Now we just need a function that takes a rule, an initial state, and the
number of steps we want to run. The function will start with the initial
state, then at each step, update the list of cells using the transition
function:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="n">rule</span><span class="p">,</span> <span class="n">initial_state</span><span class="p">,</span> <span class="n">steps</span><span class="p">):</span>
    <span class="n">t</span><span class="p">,</span> <span class="n">cells</span> <span class="o">=</span> <span class="n">transition</span><span class="p">(</span><span class="n">rule</span><span class="p">),</span> <span class="n">initial_state</span>

    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">steps</span><span class="p">):</span>
        <span class="k">yield</span> <span class="n">cells</span>
        <span class="n">cells</span> <span class="o">=</span> <span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">neighbors</span><span class="p">(</span><span class="n">cells</span><span class="p">,</span> <span class="n">i</span><span class="p">)]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">cells</span><span class="p">))]</span>
</pre></div>

<p>We talked about two ways to look at cellular automata: starting with a
single <em>on</em> cell, or starting with a random initial state.</p>

<p>Let's implement an <code>initial_state</code> function which takes a cell count as
input and returns a list of cells, all of which are <em>off</em> except the
middle one:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">initial_state</span><span class="p">(</span><span class="n">cell_count</span><span class="p">):</span>
    <span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">*</span> <span class="n">cell_count</span>
    <span class="n">result</span><span class="p">[</span><span class="n">cell_count</span> <span class="o">//</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
    <span class="k">return</span> <span class="n">result</span>
</pre></div>

<p>We'll also want a <code>random_initial_state</code> which takes a cell count and
returns a random cell list. We'll take advantage of the fact that
Python supports arbitrarily large integers natively, so we'll just
generate a random number with <code>cell_count</code> bits, then derive the cell
list from that (if a bit is <code>1</code>, the corresponding cell is <em>on</em>):</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">random</span> 

<span class="k">def</span><span class="w"> </span><span class="nf">random_initial_state</span><span class="p">(</span><span class="n">cell_count</span><span class="p">):</span>
    <span class="n">seed</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">**</span> <span class="n">cell_count</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">[</span><span class="n">seed</span> <span class="o">&amp;</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">cell_count</span><span class="p">)]</span>
</pre></div>

<p>Here is all the code in one listing:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">neighbors</span><span class="p">(</span><span class="n">cells</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">(</span><span class="n">cells</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="k">else</span> <span class="kc">False</span><span class="p">)</span> <span class="o">*</span> <span class="mi">4</span> <span class="o">+</span> \
        <span class="n">cells</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="mi">2</span> <span class="o">+</span> \
        <span class="p">(</span><span class="n">cells</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="k">if</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">cells</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span> <span class="k">else</span> <span class="kc">False</span><span class="p">)</span>

<span class="k">def</span><span class="w"> </span><span class="nf">transition</span><span class="p">(</span><span class="n">rule</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">{</span><span class="n">i</span><span class="p">:</span> <span class="n">rule</span> <span class="o">&amp;</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">8</span><span class="p">)}</span>

<span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="n">rule</span><span class="p">,</span> <span class="n">initial_state</span><span class="p">,</span> <span class="n">steps</span><span class="p">):</span>
    <span class="n">t</span><span class="p">,</span> <span class="n">cells</span> <span class="o">=</span> <span class="n">transition</span><span class="p">(</span><span class="n">rule</span><span class="p">),</span> <span class="n">initial_state</span>

    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">steps</span><span class="p">):</span>
        <span class="k">yield</span> <span class="n">cells</span>
        <span class="n">cells</span> <span class="o">=</span> <span class="p">[</span><span class="n">t</span><span class="p">[</span><span class="n">neighbors</span><span class="p">(</span><span class="n">cells</span><span class="p">,</span> <span class="n">i</span><span class="p">)]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">cells</span><span class="p">))]</span>

<span class="k">def</span><span class="w"> </span><span class="nf">initial_state</span><span class="p">(</span><span class="n">cell_count</span><span class="p">):</span>
    <span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="kc">False</span><span class="p">]</span> <span class="o">*</span> <span class="n">cell_count</span>
    <span class="n">result</span><span class="p">[</span><span class="n">cell_count</span> <span class="o">//</span> <span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
    <span class="k">return</span> <span class="n">result</span>

<span class="kn">import</span><span class="w"> </span><span class="nn">random</span> 

<span class="k">def</span><span class="w"> </span><span class="nf">random_initial_state</span><span class="p">(</span><span class="n">cell_count</span><span class="p">):</span>
    <span class="n">seed</span> <span class="o">=</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">2</span> <span class="o">**</span> <span class="n">cell_count</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
    <span class="k">return</span> <span class="p">[</span><span class="n">seed</span> <span class="o">&amp;</span> <span class="p">(</span><span class="mi">1</span> <span class="o">&lt;&lt;</span> <span class="n">i</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">cell_count</span><span class="p">)]</span>
</pre></div>

<p>Here is how we can use this to print the first 30 steps of Rule 22:</p>
<div class="highlight"><pre><span/><span class="k">for</span> <span class="n">state</span> <span class="ow">in</span> <span class="n">run</span><span class="p">(</span><span class="mi">22</span><span class="p">,</span> <span class="n">initial_state</span><span class="p">(</span><span class="mi">61</span><span class="p">),</span> <span class="mi">30</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="s1">'#'</span> <span class="k">if</span> <span class="n">e</span> <span class="k">else</span> <span class="s1">' '</span> <span class="k">for</span> <span class="n">e</span> <span class="ow">in</span> <span class="n">state</span><span class="p">]))</span>
</pre></div>

<h2>Wolfram classification</h2>

<p>Wolfram analyzed the behavior of cellular automata and classified them
in 4 classes (called <em>Wolfram classes</em>). These go beyond elementary
cellular automata to cover other cellular automata like, for example,
ones where the next generation of a cell is not determined only by the
cell and the two cells next to it, rather the neighborhood includes
next-next cells. In this post we'll stick to elementary cellular
automata though.</p>

<h3>Class 1</h3>

<p>Class 1 automata converge quickly to a uniform state. For example rule 0
becomes all <em>off</em> in one generation:</p>

<p><img src="https://vladris.com/blog/2022/07/06/0r.png" alt="image"/></p>

<p>It's complement, rule 255, becomes all <em>on</em> in one generation:</p>

<p><img src="https://vladris.com/blog/2022/07/06/255r.png" alt="image"/></p>

<h3>Class 2</h3>

<p>Class 2 automata converge quickly to a repetitive state. For example
rule 4:</p>

<p><img src="https://vladris.com/blog/2022/07/06/4r.png" alt="image"/></p>

<h3>Class 3</h3>

<p>Class 3 automata appear to remain in a random state, without converging.
Rule 22, which we started with above, exhibits this type of behavior:</p>

<p><img src="https://vladris.com/blog/2022/07/06/22r.png" alt="image"/></p>

<h3>Class 4</h3>

<p>The most interesting class of cellular automata, class 4, has a quite
remarkable behavior: areas of cells end up in static or repetitive
state, while some cells end up forming structures that interact with
each other. Rule 110 is the only elementary cellular automaton that
exhibits this behavior:</p>

<p><img src="https://vladris.com/blog/2022/07/06/110r.png" alt="image"/></p>

<h2>Turing completeness</h2>

<p>The fact that Rule 110 has areas of cells that are static or repetitive
while some other cells form structures should remind you of the
Conway's Game of Life spaceships we discussed in the previous post. In
the previous post, we saw that the Game of Life is Turing complete, and
how a Turing machine was <q>implemented</q> using spaceships as signals
<q>processed</q> by other patterns.</p>

<p>Turns out Rule 110 is also Turing complete. Stephen Wolfram conjectured
this in 1985, and the conjecture was proved in 2004 by Matthew Cook<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>.
Cook uses Rule 110 gliders (interacting structures) to emulate a cyclic
tag system. We saw in <a href="https://vladris.com/blog/2022/05/20/computability-part-3-tag-systems.html">Computability Part 3: Tag
Systems</a>
that cyclic tag systems can emulate tag systems, and an m-tag system
with \(m \gt 1\) is Turing complete.</p>

<p>Rule 110, an elementary cellular automaton, is also capable of universal
computation. And while this all might seem very abstract, cellular
automata are so simple they show up in nature:</p>

<p><img src="https://vladris.com/blog/2022/07/06/cone.jpeg" alt="image"/></p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>See <a href="https://wpmedia.wolfram.com/uploads/sites/13/2018/02/15-1-1.pdf">Universality in Elementary Cellular
Automata</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Wed, 06 Jul 2022 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/06/11/computability-part-4-conway-s-game-of-life.html</link>
      <guid>https://vladris.com/blog/2022/06/11/computability-part-4-conway-s-game-of-life.html</guid>
      <title><![CDATA[Computability Part 4: Conway's Game of Life]]></title>
      <description><![CDATA[<h1>Computability Part 4: Conway's Game of Life</h1>

<script src="https://vladris.com/static/js/gol.js"/>

<p>In the <a href="https://vladris.com/blog/2022/05/20/computability-part-3-tag-systems.html">previous
post</a>
we talked about tag systems. In this post (and the next one) we will
cover cellular automata. The most famous cellular automata is Conway's
Game of Life. Before providing the formal definitions, here is the Game
of Life in action:</p>

<div id="demo" style="overflow: scroll; text-align: center"/>

<script>animate(50, 30, [[14, 25], [15, 24], [15, 25], [15, 26], [16, 24]], "demo");</script>

<p>Formal definition:</p>

<blockquote>
<p>A cellular automaton consists of a discrete n-dimensional lattice of
cells, a set of states (for each cell), a notion of neighborhood for
each cell, and a transition function mapping the neighborhood of each
cell to a new cell state.</p>
</blockquote>

<p>The system evolves over time, where at each step, the transformation
function is applied over the lattice to determine the states of the next
generation of cells.</p>

<p>Conway's Game of Life is a cellular automaton on a 2D plane with the
following rules:</p>

<blockquote>
<ol>
<li>Any live cell with fewer than two live neighbors dies.</li>
<li>Any live cell with two or three live neighbors lives on to the
next generation.</li>
<li>Any live cell with more than three live neighbors dies.</li>
<li>Any dead cell with exactly three live neighbors becomes a live
cell.</li>
</ol>
</blockquote>

<p>In other words, a live cell stays alive during the next iteration if it
has 2 or 3 live neighbors. A dead cell becomes live if it has exactly 3
live neighbors.</p>

<p>In the case of Conway's Game of Life, the lattice is a 2D grid, we have
2 states (<em>on</em> or <em>off</em>), the neighborhood of a cell consists of all
adjacent cells (including corners), and the transition function is the
one described above. Mathematician John Conway proposed the Game of Life
in 1970.</p>

<p>The reason we started with Conway's Game of Life for discussing
cellular automata is that this simple game with simple rules exhibits
some very interesting behavior that has been classified for many years
by people toying with the simulation.</p>

<p>First, we have <em>still lives</em>, patterns that don't change while stepping
through the simulation. These patterns are stable: no cells die, no
cells become live.</p>

<div id="still" style="overflow: scroll; text-align: center"/>

<script>animate(50, 30, [[9, 14], [9, 15], [10, 14], [10, 15], [10, 33], [9, 34], [9, 35], [11, 34], [11, 35], [10, 36], [19, 14], [20, 13], [20, 15], [21, 14], [19, 33], [19, 34], [20, 33], [20, 35], [21, 34]], "still");</script>

<p>Next, we have <em>oscillators</em>, patterns that repeat with a certain
periodicity:</p>

<div id="oscillator" style="overflow: scroll; text-align: center"/>

<script>animate(50, 30, [[9, 14], [9, 15], [9, 16], [10, 33], [10, 34], [10, 35], [9, 34], [9, 35], [9, 36], [19, 14], [20, 14], [19, 15], [21, 17], [22, 16], [22, 17], [19, 31], [20, 31], [18, 32], [21, 32], [17, 33], [22, 33], [16, 34], [23, 34], [16, 35], [23, 35], [17, 36], [22, 36], [18, 37], [21, 37], [19, 38], [20, 38]], "oscillator");</script>

<p>In the above example, the last (bottom right) pattern has period 5 and
is called <em>Octagon 2</em>. The other 3 patterns all have period 2.</p>

<p>More interestingly, we have <em>spaceships</em> - these are patterns that
repeat but translate through space:</p>

<div id="ships1" style="overflow: scroll; text-align: center"/>

<script>animate(30, 30, [[14, 14], [15, 15], [16, 13], [16, 14], [16, 15]], "ships1");</script>

<div id="ships2" style="overflow: scroll; text-align: center"/>

<script>animate(30, 30, [[14, 14], [15, 14], [16, 14], [13, 15], [16, 15], [16, 16], [16, 17], [13, 18], [15, 18]], "ships2");</script>

<p>The above examples shows a couple of small spaceships, the tiny 5-cell
<em>glider</em> and the <em>lightweight spaceship</em> or <em>LWSS</em>. There are many more
spaceship patterns, some of them quite large (hundreds or even thousands
of cells).</p>

<p>Most simulations tend to eventually stabilize into a combination of
oscillators and still lives. Patterns that start from a small seed of a
handful of cells and take a long time (in terms of iterations) to
stabilize are called <em>Methuselahs</em>. Here is an example, nicknamed
<em>Acorn</em>:</p>

<div id="acorn" style="overflow: scroll; text-align: center"/>

<script>animate(50, 30, [[13, 22], [15, 21], [15, 22], [14, 24], [15, 25], [15, 26], [15, 27]], "acorn");</script>

<p>Conway conjectured that for any initial configuration, there is an upper
limit of how many live cells can ever exist. This was proved wrong by
the discovery of <em>glider guns</em>. A glider gun generates gliders every few
iterations. The gliders continue moving away from the gun, thus running
the simulation the number of live cells continues to grow.</p>

<p>One of the most popular glider guns is called <em>Gosper glider gun</em>, named
after Mathematician and programmer Bill Gosper:</p>

<div id="gun" style="overflow: scroll; text-align: center"/>

<script>animate(50, 30, [[5, 1], [6, 1], [5, 2], [6, 2], [5, 11], [6, 11], [7, 11], [4, 12], [8, 12], [3, 13], [9, 13], [3, 14], [9, 14], [6, 15], [4, 16], [8, 16], [5, 17], [6, 17], [7, 17], [6, 18], [3, 21], [4, 21], [5, 21], [3, 22], [4, 22], [5, 22], [2, 23], [6, 23], [1, 25], [2, 25], [6, 25], [7, 25], [3, 35], [4, 35], [3, 36], [4, 36]], "gun", false);</script>

<p>There are many other interesting patterns and constructions in the Game
of Life discovered throughout the years. A few examples:</p>

<ul>
<li><em>Eaters</em> are still life or oscillator patterns that can interact
and, over a number of iterations, <q>absorb</q> other patterns like
spaceships, and return to their original state.</li>
<li><em>Reflectors</em> are still life or oscillator patterns that can change
the direction of incoming spaceships, and return to their original
state.</li>
<li><em>Puffers</em> are patterns that move like spaceships but leave behind a
trail of patterns in their wake (unlike spaceships that cleanly
translate).</li>
</ul>

<p>There are many others, and combinations of them which give rise to
interesting systems like circuits and logic gates based on spaceships
and strategically placed still lives and oscillators.</p>

<h2>Implementation</h2>

<p>Let's look at a Python implementation for the Game of Life. We will use
a wrap-around space, so we'll consider cells on the last column to be
neighbors with cells on the first column and similarly cells on the last
row to be neighbors with cells on the first row.</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">make_matrix</span><span class="p">(</span><span class="n">width</span><span class="p">,</span> <span class="n">height</span><span class="p">):</span>
    <span class="k">return</span> <span class="p">[[</span><span class="kc">False</span><span class="p">]</span> <span class="o">*</span> <span class="n">width</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">height</span><span class="p">)]</span>

<span class="k">def</span><span class="w"> </span><span class="nf">neighbors</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">):</span>
    <span class="n">last_j</span> <span class="o">=</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="k">else</span> <span class="mi">0</span>
    <span class="n">last_i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">m</span><span class="p">)</span> <span class="k">else</span> <span class="mi">0</span>

    <span class="k">return</span> <span class="p">(</span><span class="n">m</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="n">last_j</span><span class="p">]</span> <span class="o">+</span>
        <span class="n">m</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">last_j</span><span class="p">]</span> <span class="o">+</span>
        <span class="n">m</span><span class="p">[</span><span class="n">last_i</span><span class="p">][</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="n">last_i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">+</span> <span class="n">m</span><span class="p">[</span><span class="n">last_i</span><span class="p">][</span><span class="n">last_j</span><span class="p">])</span>

<span class="k">def</span><span class="w"> </span><span class="nf">step</span><span class="p">(</span><span class="n">m1</span><span class="p">):</span>
    <span class="n">m2</span> <span class="o">=</span> <span class="n">make_matrix</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">m1</span><span class="p">[</span><span class="mi">0</span><span class="p">]),</span> <span class="nb">len</span><span class="p">(</span><span class="n">m1</span><span class="p">))</span>

    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">m1</span><span class="p">)):</span>
        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">m1</span><span class="p">[</span><span class="mi">0</span><span class="p">])):</span>
            <span class="n">n</span> <span class="o">=</span> <span class="n">neighbors</span><span class="p">(</span><span class="n">m1</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
                <span class="n">m2</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
            <span class="k">elif</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">2</span> <span class="ow">and</span> <span class="n">m1</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]:</span>
                <span class="n">m2</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
    <span class="k">return</span> <span class="n">m2</span>
</pre></div>

<p>To run a simulation, we also need a function to print the game state and
some initial conditions:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">print_matrix</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">m</span><span class="p">:</span>
        <span class="nb">print</span><span class="p">(</span><span class="nb">str</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">''</span><span class="p">,</span> <span class="p">[</span><span class="s1">'#'</span> <span class="k">if</span> <span class="n">c</span> <span class="k">else</span> <span class="s1">' '</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">line</span><span class="p">]))</span>

<span class="n">m</span> <span class="o">=</span> <span class="n">make_matrix</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>

<span class="n">m</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">m</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">m</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">m</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
<span class="n">m</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>

<span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">):</span>
    <span class="n">print_matrix</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
    <span class="n">m</span> <span class="o">=</span> <span class="n">step</span><span class="p">(</span><span class="n">m</span><span class="p">)</span>
</pre></div>

<p>Another very simple to implement system with powerful computational
capabilities.</p>

<h2>Turing completeness</h2>

<p>It turns out the Game of Life is Turing complete, meaning it is also
capable of universal computation. Gliders are key to this. In general,
if the behavior of cells would be either repetitive (still life or
oscillators cycle through 1 or more patterns) or chaotic, it would be
hard to perform any computation. But gliders <q>move</q> and can interact
with each other, thus enabling some non-chaotic processes.</p>

<p>We briefly discussed above how Game of Life patterns can be combined to
form circuits that can process signals (in the form of spaceships) like
logic gates and <q>memory storage</q>. Paul Rendell <q>implemented</q> a
universal Turing machine in the Game of Life. His website
(<a href="http://rendell-attic.org/gol/tm.htm">http://rendell-attic.org/gol/tm.htm</a>) covers the details, which we
won't go into due to the complexity. Suffice to say the patterns
emerging in the Game of Life can be combined to build such a device.
Paul also wrote a book about it<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>.</p>

<p>We again encountered a system capable of computing anything computable,
based only on a matrix of cells and a couple of rules (live cells with 2
or 3 neighbors stay alive, dead cells with exactly 3 neighbors become
live).</p>

<p>The website <a href="https://conwaylife.com/">https://conwaylife.com/</a> includes a lot of details on
Conway's Game of Life, various patterns discovered, and a forum where
people discuss their exploration of the system.</p>

<p>In the next post, we'll look at even simpler cellular automata:
elementary cellular automata where cells have 2 possible states and 2
neighbors.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>See <a href="https://www.amazon.com/Machine-Universality-Emergence-Complexity-Computation-ebook/dp/B012A45DVO/">Turing Machine Universality of the Game of
Life</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sat, 11 Jun 2022 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/05/20/computability-part-3-tag-systems.html</link>
      <guid>https://vladris.com/blog/2022/05/20/computability-part-3-tag-systems.html</guid>
      <title><![CDATA[Computability Part 3: Tag Systems]]></title>
      <description><![CDATA[<h1>Computability Part 3: Tag Systems</h1>

<p>In the <a href="https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html">previous
post</a>
we talked about universal Turing machines and looked at some very small
machines that are still capable of computing anything that can be
computed (the Turing-completeness property). In this post, we'll look
at another model for computation: tag systems.</p>

<blockquote>
<p>A tag system operates on a string of symbols by reading the symbol
from the head of the string, deleting a constant number of symbols
from the head of the string, and appending one or more symbols to the
tail of the string based on the symbol read from the head.</p>
</blockquote>

<p>Formally:</p>

<blockquote>
<p>A tag system is a triplet \(\langle m, A, P \rangle\).</p>

<ul>
<li>\(m\) is a positive integer, called the <em>deletion number</em>, which
specifies how many symbols are deleted from the head during each
iteration.</li>
<li>\(A\) is a finite alphabet of symbols, including a special <em>halting
symbol</em>.</li>
<li>\(P\) is a set of <em>production rules</em> which map each symbol in \(A\) to
a string of symbols or <em>words</em> from \(A\) (to be appended to the end
of the string).</li>
</ul>
</blockquote>

<p>Tag systems were specified by Emil Leon Post in 1943, 7 years after
Turing Machines. We usually refer to tag systems as <em>m-tag systems</em>
where \(m\) is the deletion number from the definition above.</p>

<p>At each step, \(x\) is read from the head of the string, \(m\) symbols are
deleted, and \(P(x)\) is appended to the end of the string. The tag system
halts when \(x\) is the halting symbol.</p>

<p>An alternative definition that doesn't require a halting symbol
considers as halting all words that are smaller than \(m\). In this case,
the tag system halts when the string shrinks sufficiently. Yet another
alternative considers as halting the empty string. In this case, the tag
system halts when the string becomes empty.</p>

<p>Let's look at a Python implementation for a tag system:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">tag_system</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="c1"># Repeat until the string is empty or we see the halting symbol</span>
    <span class="k">while</span> <span class="n">string</span> <span class="ow">and</span> <span class="n">string</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">productions</span><span class="p">:</span>
        <span class="n">string</span> <span class="o">=</span> <span class="n">string</span><span class="p">[</span><span class="n">m</span><span class="p">:]</span> <span class="o">+</span> <span class="n">productions</span><span class="p">[</span><span class="n">string</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>

        <span class="k">yield</span> <span class="n">string</span>
</pre></div>

<p>As an example, let's take the tag system with
\(m = 2, A = \langle a, b, H \rangle\), and the production rules</p>

<table>
<thead>
<tr>
<th>Symbol</th>
<th>Word</th>
</tr>
</thead>

<tbody>
<tr>
<td>a</td>
<td>aab</td>
</tr>
<tr>
<td>b</td>
<td>H</td>
</tr>
</tbody>
</table>

<p>Starting with the string <code>aa</code>, the steps are:</p>
<div class="highlight"><pre><span/>aa              // Erase 2 symbols from head, a -&gt; aab
  aab           // Erase 2 symbols from head, a -&gt; aab
    baab        // Erase 2 symbols from head, b -&gt; H
      abH       // Erase 2 symbols from head, a -&gt; aab
        Haab    // Halt
</pre></div>

<p>Using our <code>tag_system()</code> function implemented above:</p>
<div class="highlight"><pre><span/><span class="n">productions</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s1">'a'</span><span class="p">:</span> <span class="s1">'aab'</span><span class="p">,</span>
    <span class="s1">'b'</span><span class="p">:</span> <span class="s1">'H'</span><span class="p">,</span>
<span class="p">}</span>

<span class="n">string</span> <span class="o">=</span> <span class="s1">'aa'</span>

<span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">for</span> <span class="n">string</span> <span class="ow">in</span> <span class="n">tag_system</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
</pre></div>

<p>Tag systems are simple, even simpler than Turing machines. Remember we
defined a Turing machine as a 7-tuple while tag systems are represented
by triplets. Turing machines have states, and depending on the state, a
machine takes different actions. Tag systems technically have a single
state: when a symbol is read from the head of the string, the same thing
will always happen: \(m\) symbols are deleted from the head and the
corresponding production rule determines what word to append to the tail
of the string. Even so, tag systems are Turing-complete.</p>

<h2>Turing completeness</h2>

<p>For \(m \gt 1\), m-tag systems are Turing complete. For any Turing
machine, there is an m-tag system that can emulate that Turing machine.
John Cocke and Marvin Minsky showed in 1964 how a 2-tag system can
emulate a universal Turing machine<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. That means that such a super
simple system is also capable of universal computation!</p>

<p>But it gets even simpler.</p>

<h2>Cyclic tag systems</h2>

<p>A cyclic tag system is a modification of tag systems where:</p>

<ul>
<li>\(m = 1\): only one symbol is deleted from the head of the string.</li>
<li>The alphabet consists of only <code>0</code> and <code>1</code>.</li>
<li>Instead of production rules, we use a finite list of words (on the
alphabet consisting of only <code>0</code> and <code>1</code>) called <em>productions</em>.</li>
</ul>

<p>Instead of production rules, we cycle through the list of productions.
We start from the head of the list of productions. At each step, if the
symbol at the head of the string is <code>1</code>, we append the production to the
end of the string. If the symbol at the head of the string is <code>0</code>, we
don't append anything. We then move to the next production in the list
for the next step. Once we exhaust the list of productions, we loop
around to the head (this inspired the <em>cyclic</em> name).</p>

<p>Here is a Python implementation for a cyclic tag system:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="c1"># Keeps track of current production</span>
    <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>

    <span class="c1"># Repeat until the string is empty</span>
    <span class="k">while</span> <span class="n">string</span><span class="p">:</span>
        <span class="n">string</span> <span class="o">=</span> <span class="n">string</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="o">+</span> <span class="p">(</span><span class="n">productions</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="k">if</span> <span class="n">string</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'1'</span> <span class="k">else</span> <span class="s1">''</span><span class="p">)</span>

        <span class="c1"># Update current production</span>
        <span class="n">i</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">productions</span><span class="p">):</span>
            <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>

        <span class="k">yield</span> <span class="n">string</span>
</pre></div>

<p>For example, we will use the production rules <code>11</code>, <code>01</code>, <code>00</code>. With an
initial string <code>1</code>, the steps are:</p>
<div class="highlight"><pre><span/>1               // Append production 11
 11             // Append production 01
  101           // Append production 00
   0100         // Current production 11 (won't append since head is 0)
    100         // Append production 01
     0001       // Current production 00 (won't append since head is 0)
      001       // Current production 11 (won't append since head is 0)
       01       // Current production 01 (won't append since head is 0)
        1       // Append production 00
         00     // Current production 11 (won't append since head is 0)
          0     // Current production 01 (won't append since head is 0)
                // Halts
</pre></div>

<p>Using our Python implementation:</p>
<div class="highlight"><pre><span/><span class="n">productions</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'11'</span><span class="p">,</span> <span class="s1">'01'</span><span class="p">,</span> <span class="s1">'00'</span><span class="p">]</span>

<span class="n">string</span> <span class="o">=</span> <span class="s1">'1'</span>

<span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">for</span> <span class="n">string</span> <span class="ow">in</span> <span class="n">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
</pre></div>

<p>Cyclic tag systems are simpler than tag systems since \(m\) is fixed to
<code>1</code>, the alphabet is fixed to <code>0</code> and <code>1</code>, and productions are a
represented as a cyclic list rather than a map of symbols to words. Even
so, a cyclic tag system can emulate any m-tag system.</p>

<h2>Emulating tag systems with cyclic tag systems</h2>

<p>An m-tag system with \(n\) symbols \(\lbrace a_1, a_2, ... a_n \rbrace\) and
their corresponding production rules \(\lbrace P_1, P_2, ... P_n \rbrace\)
can be translated to a cyclic tag system with \(m * n\) productions where
the first \(n\) productions \(\lbrace P'_1, P'_2, ... P'_n \rbrace\) are
encodings of their respective \(P\)-productions in the m-tag system and
the rest are empty strings.</p>

<p>Productions in the m-tag system are words over the alphabet \(A\). We
encode each symobl in \(A\) as a binary string of length \(n\), with a <code>1</code>
in the \(k\)-th position for \(a_k\). For example, for \(n = 3\) and the
alphabet \(A = \lbrace a_1, a_2, a_3 \rbrace\), we encode \(a_1\) as <code>100</code>,
\(a_2\) as <code>010</code>, \(a_3\) as <code>001</code>. Since a production \(P_k\) is a sequence
of symbols, we can similarly translate it into an encoded representation
\(P'_k\) using symbols <code>0</code> and <code>1</code>.</p>

<p>Our first example was the 2-tag system with the alphabet
\(A = \langle a, b, H \rangle\), and the production rules</p>

<table>
<thead>
<tr>
<th>Symbol</th>
<th>Word</th>
</tr>
</thead>

<tbody>
<tr>
<td>a</td>
<td>aab</td>
</tr>
<tr>
<td>b</td>
<td>H</td>
</tr>
<tr>
<td>H</td>
<td>H</td>
</tr>
</tbody>
</table>

<p>Here we added the production rule <code>H -&gt; H</code> for completeness, so we have
exactly \(n\) production rules.</p>

<p>Translating this into a cyclic tag system, \(a, b, H\) become <code>100</code>,
<code>010</code>, and <code>001</code> respectively. The production rules translate as:</p>

<blockquote>
<p><code>a -&gt; aab</code> becomes <code>100100010</code></p>

<p><code>b -&gt; H</code> becomes <code>001</code></p>

<p><code>H -&gt; H</code> becomes <code>001</code></p>
</blockquote>

<p>The full list of production for the cyclic tag system is
<code>100100010, 001, 001, -, -, -</code> where <code>-</code> is the empty string.</p>

<p>The initial string <code>aa</code> becomes <code>100100</code>, so our emulation is:</p>
<div class="highlight"><pre><span/>100100                      // * Emulated production rule a -&gt; aab
 00100100100010             // P = 001 (but head is 0)
  0100100100010             // P = 001 (but head is 0)
   100100100010             // P = empty string
    00100100010             // P = empty string, head is 0
     0100100010             // P = empty string, head is 0
      100100010             // * Emulated production rule a -&gt; aab
       00100010100100010    // P = 001 (but head is 0)
        0100010100100010    // P = 001 (but head is 0)
         100010100100010    // P = empty string
          00010100100010    // P = empty string, head is 0
           0010100100010    // P = empty string, head is 0
            010100100010    // P = 100100010 (but is 0)
             10100100010    // * Emulated production rule b -&gt; H
              0100100010001 // P = 001 (but head is 0)
               100100010001 // P = empty string
                ...
</pre></div>

<p>Using our Python implementation:</p>
<div class="highlight"><pre><span/><span class="n">productions</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'100100010'</span><span class="p">,</span> <span class="s1">'001'</span><span class="p">,</span> <span class="s1">'001'</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">''</span><span class="p">]</span>

<span class="n">string</span> <span class="o">=</span> <span class="s1">'100100'</span>

<span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">for</span> <span class="n">string</span> <span class="ow">in</span> <span class="n">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
</pre></div>

<p>Note in this case the cyclic tag system won't halt when the emulated
m-tag system halts, since that would be an emulated halt. But we can
stop it by checking whether the first 3 symbols represent the encoding
of <code>H</code>. We do this every sixth step, since we have a 2-tag system with 3
symbols, which means we emulate 1 step of the tag system with 6 steps of
the cyclic tag system.</p>
<div class="highlight"><pre><span/><span class="n">productions</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'100100010'</span><span class="p">,</span> <span class="s1">'001'</span><span class="p">,</span> <span class="s1">'001'</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">''</span><span class="p">]</span>

<span class="n">i</span><span class="p">,</span> <span class="n">string</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">'100100'</span>

<span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">for</span> <span class="n">string</span> <span class="ow">in</span> <span class="n">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="nb">print</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>

    <span class="n">i</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="mi">6</span>

    <span class="c1"># Break if halting symbol is at the head of the string</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">string</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'001'</span><span class="p">:</span>
        <span class="k">break</span>
</pre></div>

<p>Or, an updated example that prints every sixth step and translates from
the cyclic tag system encoding to the original symbols:</p>
<div class="highlight"><pre><span/><span class="n">productions</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'100100010'</span><span class="p">,</span> <span class="s1">'001'</span><span class="p">,</span> <span class="s1">'001'</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">''</span><span class="p">,</span> <span class="s1">''</span><span class="p">]</span>

<span class="n">symbols</span> <span class="o">=</span> <span class="p">{</span>
    <span class="s1">'100'</span><span class="p">:</span> <span class="s1">'a'</span><span class="p">,</span>
    <span class="s1">'010'</span><span class="p">:</span> <span class="s1">'b'</span><span class="p">,</span>
    <span class="s1">'001'</span><span class="p">:</span> <span class="s1">'H'</span><span class="p">,</span>
<span class="p">}</span>

<span class="k">def</span><span class="w"> </span><span class="nf">translate</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
    <span class="k">return</span> <span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">([</span><span class="n">symbols</span><span class="p">[</span><span class="n">s</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="mi">3</span><span class="p">]]</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">),</span> <span class="mi">3</span><span class="p">)])</span>

<span class="n">i</span><span class="p">,</span> <span class="n">string</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="s1">'100100'</span>

<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">string</span><span class="si">}</span><span class="s1"> (</span><span class="si">{</span><span class="n">translate</span><span class="p">(</span><span class="n">string</span><span class="p">)</span><span class="si">}</span><span class="s1">)'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">string</span> <span class="ow">in</span> <span class="n">cyclic_tag_system</span><span class="p">(</span><span class="n">productions</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
    <span class="n">i</span> <span class="o">=</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="mi">6</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">string</span><span class="si">}</span><span class="s1"> (</span><span class="si">{</span><span class="n">translate</span><span class="p">(</span><span class="n">string</span><span class="p">)</span><span class="si">}</span><span class="s1">)'</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">string</span><span class="p">[:</span><span class="mi">3</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'001'</span><span class="p">:</span>
            <span class="k">break</span>
</pre></div>

<p>Running this code should be the emulated equivalent of our first example
in this post.</p>

<p>Since m-tag systems (with \(m \gt 1\)) are Turing-complete and cyclic tag
systems can emulate any m-tag system, it follows that cyclic tag systems
are also Turing complete. We can compute anything that is computable
with the alphabet <code>0</code>, <code>1</code>, and a list of words over this alphabet!</p>

<p>In the next post, we will continue our exploration of simple systems
capable of universal computation with cellular automata.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>See <a href="https://dl.acm.org/doi/pdf/10.1145/321203.321206">Universality of Tag Systems With P =
2</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Fri, 20 May 2022 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html</link>
      <guid>https://vladris.com/blog/2022/04/03/computability-part-2-turing-machines.html</guid>
      <title><![CDATA[Computability Part 2: Turing Machines]]></title>
      <description><![CDATA[<h1>Computability Part 2: Turing Machines</h1>

<p>In the <a href="https://vladris.com/blog/2022/02/12/computability-part-1-a-short-history.html">previous
post</a>,
we looked at a history of what would become computer science. In this
post, we'll focus on Turing machines and Turing completeness.</p>

<p>The informal definition we gave to a Turing machine in the previous post
is:</p>

<blockquote>
<p>An abstract computer consisting of an infinite tape of cells, a head
that can read from a cell, write to a cell, and move left or right
over the tape, and a set of rules which direct the head based on the
read symbol and the current state of the machine.</p>
</blockquote>

<p>Formally:</p>

<blockquote>
<p>A Turing machine is a 7-tuple
\(M = \langle Q, q_0, F, \Gamma, b, \Sigma, \delta \rangle\).</p>

<ul>
<li>\(Q \ne \varnothing\) is a finite set of <em>states</em>. These are all the
states the machine can be in.</li>
<li>\(q_0 \in Q\) is the <em>initial state</em>. This is the state the machine
starts in.</li>
<li>\(F \subseteq Q\) is the set of <em>final states</em>. When the machine
reaches one of the final states, it <em>halts</em> - it stops execution.</li>
<li>\(\Gamma \ne \varnothing\) is a finite set of <em>tape symbols</em>. These
are all the symbols that can appear on the tape.</li>
<li>\(b \in \Gamma\) is the <em>blank symbol</em>, one of the possible <em>tape
symbols</em>. The only symbol allowed to occur on the tape infinitely
often at any step.</li>
<li>\(\Sigma \subseteq \Gamma \setminus \lbrace b \rbrace\) is the set
of <em>input symbols</em> allowed to appear in the initial tape contents
(not written by the machine during execution). These symbols can
be the whole alphabet (except the blank symbol), or a subset of
the alphabet.</li>
<li>\(\delta: (Q \setminus F) \times \Gamma \to Q \times \Gamma \times \lbrace L, R \rbrace\)
is a function called the <em>transition function</em>. This functions
takes as input the current machine state and the symbol on the
tape. It outputs the new machine state, the symbol to overwrite
the current tape symbol, and the head movement (either left or
right). Note the function domain excludes the final states - once
the machine reaches a state in \(F\), it halts so no more
transitions happen.</li>
</ul>
</blockquote>

<p>Alternately, the transition function can be defined as a partial
function
\(\delta: Q \times \Gamma \hookrightarrow Q \times \Gamma \times \lbrace L, R \rbrace\),
where the machine halts if the function is undefined for the given
combination of machine state and tape symbol. In some compact Turing
machines (like we'll see below), \(F\) is empty. There is not <em>final
state</em>, rather we halt when encountering a certain combination of
machine state and tape symbol for which no transition is defined.</p>

<p>Note this definition allows for some very uninteresting machines: a
machine that only has an initial and a final state
(\(Q = \lbrace q_0, f \rbrace\)) and, for any input symbol in \(\Gamma\),
the transition function moves the machine into the final state. This is
a Turing machine, but it can't really compute much. Something more is
needed.</p>

<h2>Universal Turing machines</h2>

<p>A <em>universal Turing machine</em> is a Turing machine that can simulate
another, arbitrary, Turing machine on arbitrary input. That is, it can
read the description of a Turing machine and that machine's input as
its own input, then simulate the execution of that machine.</p>

<p>With this definition, a universal Turing machine can compute anything
any other Turing machine can compute (anything that is computable).</p>

<p>Marvin Minsky discovered a universal Turing machine that requires only 7
states and 2 symbols. Yurii Rogozhin discovered a machine with only 4
states and 6 symbols. Let's call the states
\(Q = \lbrace A, B, C, D \rbrace\) and the symbols
\(\Gamma = \lbrace 0, 1, 2, 3, 4, 5 \rbrace\).</p>

<p><strong>(4, 6) Turing Machine</strong></p>

<table>
<thead>
<tr>
<th style="text-align: center"/>
<th style="text-align: center">A</th>
<th style="text-align: center">B</th>
<th style="text-align: center">C</th>
<th style="text-align: center">D</th>
</tr>
</thead>

<tbody>
<tr>
<td style="text-align: center">0</td>
<td style="text-align: center">3,L,A</td>
<td style="text-align: center">4,R,B</td>
<td style="text-align: center">0,R,C</td>
<td style="text-align: center">4,R,D</td>
</tr>
<tr>
<td style="text-align: center">1</td>
<td style="text-align: center">2,R,A</td>
<td style="text-align: center">2,L,C</td>
<td style="text-align: center">3,R,D</td>
<td style="text-align: center">5,L,B</td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">1,L,A</td>
<td style="text-align: center">3,R,B</td>
<td style="text-align: center">1,R,C</td>
<td style="text-align: center">3,R,D</td>
</tr>
<tr>
<td style="text-align: center">3</td>
<td style="text-align: center">4,R,A</td>
<td style="text-align: center">2,L,B</td>
<td style="text-align: center">HALT</td>
<td style="text-align: center">HALT</td>
</tr>
<tr>
<td style="text-align: center">4</td>
<td style="text-align: center">3,L,A</td>
<td style="text-align: center">0,L,B</td>
<td style="text-align: center">5,R,A</td>
<td style="text-align: center">5,L,B</td>
</tr>
<tr>
<td style="text-align: center">5</td>
<td style="text-align: center">4,R,D</td>
<td style="text-align: center">1,R,B</td>
<td style="text-align: center">0,R,A</td>
<td style="text-align: center">1,R,D</td>
</tr>
</tbody>
</table>

<p>The above table describes the transition function of the Turing machine.
For example, if the machine is in state <code>A</code> and the read tape symbol is
<code>5</code>, we can look up the <code>A</code> column and <code>5</code> row to find the transition
<code>4,R,D</code>. This means <q>print <code>4</code> on the tape (overwriting the current
symbol), move the head right (<code>R</code>), machine is now in state <code>D</code></q>.</p>

<p>We're using the partial transition function definition, so instead of
defining one or more explicit final states (\(F\)), we don't define a
transition when the tape symbol is <code>3</code> and the machine is in state <code>C</code>
or state <code>D</code>.</p>

<h2>Implementation</h2>

<p>Let's look at a Python implementation of Turing machines. First, let's
implement the tape we will be using. Theoretically this is an infinite
tape. To simulate this in software, we will use a list and whenever we
move the head left or right beyond the list, we extend the list with an
additional blank symbol:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Tape</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">tape</span><span class="p">,</span> <span class="n">head</span> <span class="o">=</span> <span class="mi">0</span><span class="p">):</span>
        <span class="c1"># Initial tape should have at least one symbol</span>
        <span class="k">assert</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">tape</span><span class="p">)</span> <span class="o">&gt;=</span> <span class="mi">1</span><span class="p">)</span>
        <span class="c1"># Tape head should be a valid index</span>
        <span class="k">assert</span><span class="p">(</span><span class="mi">0</span> <span class="o">&lt;=</span> <span class="n">head</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">tape</span><span class="p">))</span>

        <span class="bp">self</span><span class="o">.</span><span class="n">tape</span> <span class="o">=</span> <span class="n">tape</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">head</span> <span class="o">=</span> <span class="n">head</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">read</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">tape</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">head</span><span class="p">]</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">write</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">symbol</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">tape</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">head</span><span class="p">]</span> <span class="o">=</span> <span class="n">symbol</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">move_left</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="c1"># If attempting to move left out of bounds, extend tape left</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">head</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">tape</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">head</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">def</span><span class="w"> </span><span class="nf">move_right</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">head</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="c1"># If attempting to move right out of bounds, extend tape right</span>
        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">head</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">tape</span><span class="p">):</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">tape</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</pre></div>

<p>We'll implement a machine that takes a tape, a transition table, and an
initial state, and runs until it halts:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">machine</span><span class="p">(</span><span class="n">tape</span><span class="p">,</span> <span class="n">transitions</span><span class="p">,</span> <span class="n">state</span><span class="p">):</span>
    <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
        <span class="n">symbol</span> <span class="o">=</span> <span class="n">tape</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>

        <span class="c1"># If no transition is defined for the current state and symbol, halt</span>
        <span class="k">if</span> <span class="ow">not</span> <span class="n">transitions</span><span class="p">[</span><span class="n">state</span><span class="p">][</span><span class="n">symbol</span><span class="p">]:</span>
            <span class="k">break</span>

        <span class="n">new_symbol</span><span class="p">,</span> <span class="n">direction</span><span class="p">,</span> <span class="n">new_state</span> <span class="o">=</span> <span class="n">transitions</span><span class="p">[</span><span class="n">state</span><span class="p">][</span><span class="n">symbol</span><span class="p">]</span>

        <span class="n">tape</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">new_symbol</span><span class="p">)</span>
        <span class="n">tape</span><span class="o">.</span><span class="n">move_left</span><span class="p">()</span> <span class="k">if</span> <span class="n">direction</span> <span class="o">==</span> <span class="s1">'L'</span> <span class="k">else</span> <span class="n">tape</span><span class="o">.</span><span class="n">move_right</span><span class="p">()</span>
        <span class="n">state</span> <span class="o">=</span> <span class="n">new_state</span>
</pre></div>

<p>To stich this together, we need a transition table and initial tape
state. We'll use the Rogozhin (4, 6) machine:</p>
<div class="highlight"><pre><span/><span class="c1">## Machine states</span>
<span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">,</span> <span class="n">C</span><span class="p">,</span> <span class="n">D</span> <span class="o">=</span> <span class="s1">'A'</span><span class="p">,</span> <span class="s1">'B'</span><span class="p">,</span> <span class="s1">'C'</span><span class="p">,</span> <span class="s1">'D'</span>

<span class="c1">## Left and right</span>
<span class="n">L</span><span class="p">,</span> <span class="n">R</span> <span class="o">=</span> <span class="s1">'L'</span><span class="p">,</span> <span class="s1">'R'</span>

<span class="c1">## Rogozhin 4-state, 6-symbol Turing machine</span>
<span class="n">transition</span> <span class="o">=</span> <span class="p">{</span>
    <span class="n">A</span><span class="p">:</span> <span class="p">[(</span><span class="mi">3</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span> <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">D</span><span class="p">)],</span>
    <span class="n">B</span><span class="p">:</span> <span class="p">[(</span><span class="mi">4</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">B</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">C</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">B</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">B</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">B</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">B</span><span class="p">)],</span>
    <span class="n">C</span><span class="p">:</span> <span class="p">[(</span><span class="mi">0</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">C</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">D</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">C</span><span class="p">),</span> <span class="kc">None</span><span class="p">,</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">A</span><span class="p">),</span> <span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">A</span><span class="p">)],</span>
    <span class="n">D</span><span class="p">:</span> <span class="p">[(</span><span class="mi">4</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">D</span><span class="p">),</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">B</span><span class="p">),</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">D</span><span class="p">),</span> <span class="kc">None</span><span class="p">,</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="n">L</span><span class="p">,</span> <span class="n">B</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">R</span><span class="p">,</span> <span class="n">D</span><span class="p">)],</span>
<span class="p">}</span>
</pre></div>

<p>This machine is a universal Turing machine, meaning it can simulate any
other turing machine, thus is capable of universal computation (can
compute anything that is computable).</p>

<h2>Turing-completeness</h2>

<blockquote>
<p>A Turing-complete system is any system capable of simulating any
Turing machine.</p>
</blockquote>

<p>Turing-completeness is a way of expressing the computational power of a
given system. A Turing-complete system is capable of universal
computation. The small Rogozhin (4, 6) machine, since it is a universal
Turing machine, is Turing-complete.</p>

<p>More so, the fact that we can simulate this machine in the Python
programming language proves that the Python language itself is
Turing-complete.</p>

<h2>Esoteric Turing-complete systems</h2>

<p>If we weaken some of the constraints for Turing machines, there are even
smaller <em>weak</em> universal Turing machines. For example, if we allow the
tape to contain an infinitely repeated sequence of symbols, or we don't
require the machine to ever halt.</p>

<p>The smallest weak Turing machine is a Turing machine consisting of 2
states and 3 symbols. Let's call the states \(Q = \lbrace A, B \rbrace\)
and the symbols \(\Gamma = \lbrace 0, 1, 2 \rbrace\).</p>

<p><strong>(2, 3) Turing Machine</strong></p>

<table>
<thead>
<tr>
<th style="text-align: center"/>
<th style="text-align: center">A</th>
<th style="text-align: center">B</th>
</tr>
</thead>

<tbody>
<tr>
<td style="text-align: center">0</td>
<td style="text-align: center">1,R,B</td>
<td style="text-align: center">2,L,A</td>
</tr>
<tr>
<td style="text-align: center">1</td>
<td style="text-align: center">2,L,A</td>
<td style="text-align: center">2,R,B</td>
</tr>
<tr>
<td style="text-align: center">2</td>
<td style="text-align: center">1,L,A</td>
<td style="text-align: center">0,R,A</td>
</tr>
</tbody>
</table>

<p>Stephen Wolfram in <a href="https://www.goodreads.com/book/show/238558.A_New_Kind_of_Science">A New Kind of
Science</a>
(a book we'll get back to in a future post) described a 2-state
5-symbol universal Turing machine and conjectured the 2-state 3-symbol
machine is also universal. The universality of the 2-state 3-symbol
machine was proved in 2007.</p>

<p>In terms of Turing-complete programming languages, a somewhat famous
esoteric programming langue is
<a href="https://en.wikipedia.org/wiki/Brainfuck">Brainfuck</a>. Brainfuck uses a
byte array (tape), a data pointer (index in the array), and 8 symbols:
<code>&gt;</code>, <code>&lt;</code>, <code>+</code>, <code>-</code>, <code>.</code>, <code>,</code>, <code>[</code>, <code>]</code>. The symbols are interpreted as:</p>

<ul>
<li><code>&gt;</code>: Increment the data pointer (move head right).</li>
<li><code>&lt;</code>: Decrement the data pointer (move head left).</li>
<li><code>+</code>: Increment array value at data pointer.</li>
<li><code>-</code>: Decrement array value at data pointer.</li>
<li><code>.</code>: Output value at data pointer.</li>
<li><code>,</code>: Read 1 byte of input and store at data pointer.</li>
<li><code>[</code>: If the byte at data pointer is 0, jump right to the matching
<code>]</code>, else increment data pointer</li>
<li><code>]</code>: If the byte at data pointer is not 0, jump left to the matching
<code>[</code>, else decrement data pointer</li>
</ul>

<p>This simple language is very much modeled after a Turing machine. Here
is <q>Hell World!</q> in Brainfuck:</p>
<div class="highlight"><pre><span/>++++++++[&gt;++++[&gt;++&gt;+++&gt;+++&gt;+&lt;&lt;&lt;&lt;-]&gt;+&gt;+&gt;-&gt;&gt;+[&lt;]&lt;-]&gt;&gt;.&gt;
---.+++++++..+++.&gt;&gt;.&lt;-.&lt;.+++.------.--------.&gt;&gt;+.&gt;++.
</pre></div>

<p>Since the language definition is so simple, it is very easy to write a
Brainfuck interpreter:</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>

<span class="k">def</span><span class="w"> </span><span class="nf">bf</span><span class="p">(</span><span class="n">program</span><span class="p">):</span>
    <span class="c1"># Data array, data pointer, and code pointer</span>
    <span class="n">data</span><span class="p">,</span> <span class="n">dp</span><span class="p">,</span> <span class="n">cp</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>

    <span class="k">while</span> <span class="n">cp</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">program</span><span class="p">):</span>
        <span class="k">match</span> <span class="n">program</span><span class="p">[</span><span class="n">cp</span><span class="p">]:</span>
            <span class="k">case</span> <span class="s1">'&lt;'</span><span class="p">:</span>
                <span class="n">dp</span> <span class="o">-=</span> <span class="mi">1</span>
            <span class="k">case</span> <span class="s1">'&gt;'</span><span class="p">:</span>
                <span class="n">dp</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="k">if</span> <span class="n">dp</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
                    <span class="n">data</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
            <span class="k">case</span> <span class="s1">'+'</span><span class="p">:</span>
                <span class="n">data</span><span class="p">[</span><span class="n">dp</span><span class="p">]</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="k">case</span> <span class="s1">'-'</span><span class="p">:</span>
                <span class="n">data</span><span class="p">[</span><span class="n">dp</span><span class="p">]</span> <span class="o">-=</span> <span class="mi">1</span>
            <span class="k">case</span> <span class="s1">'.'</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="nb">chr</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">dp</span><span class="p">]),</span> <span class="n">end</span><span class="o">=</span><span class="s1">''</span><span class="p">)</span>
            <span class="k">case</span> <span class="s1">','</span><span class="p">:</span>
                <span class="n">data</span><span class="p">[</span><span class="n">dp</span><span class="p">]</span> <span class="o">=</span> <span class="nb">ord</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
            <span class="k">case</span> <span class="s1">'['</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="n">dp</span><span class="p">]</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">opened</span> <span class="o">=</span> <span class="mi">1</span>
                    <span class="k">while</span> <span class="n">opened</span><span class="p">:</span>
                        <span class="n">cp</span> <span class="o">+=</span> <span class="mi">1</span>
                        <span class="k">if</span> <span class="n">program</span><span class="p">[</span><span class="n">cp</span><span class="p">]</span> <span class="o">==</span> <span class="s1">']'</span><span class="p">:</span>
                            <span class="n">opened</span> <span class="o">-=</span> <span class="mi">1</span>
                        <span class="k">elif</span> <span class="n">program</span><span class="p">[</span><span class="n">cp</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'['</span><span class="p">:</span>
                            <span class="n">opened</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="k">case</span> <span class="s1">']'</span><span class="p">:</span>
                <span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="n">dp</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                    <span class="n">opened</span> <span class="o">=</span> <span class="mi">1</span>
                    <span class="k">while</span> <span class="n">opened</span><span class="p">:</span>
                        <span class="n">cp</span> <span class="o">-=</span> <span class="mi">1</span>
                        <span class="k">if</span> <span class="n">program</span><span class="p">[</span><span class="n">cp</span><span class="p">]</span> <span class="o">==</span> <span class="s1">'['</span><span class="p">:</span>
                            <span class="n">opened</span> <span class="o">-=</span> <span class="mi">1</span>
                        <span class="k">elif</span> <span class="n">program</span><span class="p">[</span><span class="n">cp</span><span class="p">]</span> <span class="o">==</span> <span class="s1">']'</span><span class="p">:</span>
                            <span class="n">opened</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">cp</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>

<p>Also note that any programming language that can implement a Brainfuck
interpreter is Turing-complete (since Brainfuck is Turing-complete).</p>

<p>There's also some surprising proofs of unintentional
Turing-completeness. For example, C++ template metaprogramming was
proved to be Turing-complete (not the C++ language itself, which is
obviously Turing-complete, just the template part alone). Magic: The
Gathering <a href="https://arxiv.org/abs/1904.09828">is also Turing-complete</a>.
Turing-completeness comes in many forms. In the next posts, we'll look
at some other models of universal computation: tag systems and cellular
automata.</p>
]]></description>
      <pubDate>Sun, 03 Apr 2022 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2022/02/12/computability-part-1-a-short-history.html</link>
      <guid>https://vladris.com/blog/2022/02/12/computability-part-1-a-short-history.html</guid>
      <title><![CDATA[Computability Part 1: A Short History]]></title>
      <description><![CDATA[<h1>Computability Part 1: A Short History</h1>

<blockquote>
<p>An algorithm (/ËÃ¦lÉ¡ÉrÉªÃ°Ém/ ) is a finite sequence of well-defined
instructions, typically used to solve a class of specific problems or
to perform a computation.</p>
</blockquote>

<h2>Ancient computers</h2>

<p>The first computer (we know of) is the Antikythera mechanism. It was
found in 1901 in a shipwreck. The device was built sometime between 100
BC and 150 BC and uses gears to predict astronomical positions of the
Sun, Moon, and planets through the zodiac.</p>

<p><img src="https://vladris.com/blog/2022/02/12/device.jpg" alt="image"/></p>

<p><em>Image from Wikimedia Commons user Marsyas, <a href="https://creativecommons.org/licenses/by/2.5/">CC BY
2.5</a></em></p>

<p>This millennia old device is a hand-powered analog computer. Humanity
has been looking at automating computation for quite some time.</p>

<h2>The father of computer science</h2>

<p>Skipping forward a few hundred years, the famous Gottfried Wilhelm
Leibniz (1646-1714) designed the first device that could perform the 4
arithmetic operations and used an internal memory. He also invented the
binary system, and his Algebra of Thought is a precursor to Boolean
Algebra. Leibniz is famous as a mathematician (inventing calculus
independently of Isaac Newton), but some also call him <em>the father of
computer science</em>.</p>

<p>After creating his arithmetic machine, Leibniz dreamt of a machine that
could manipulate symbols in order to decide the truth value of
mathematical statements.</p>

<h2>The Difference Engine and the Analytical Engine</h2>

<p>Over a century later, Charles Babbage (1791-1871) invents the Difference
Engine, a mechanical calculator that can tabulate polynomial functions.
Babbage created a small version of this, the Difference Engine 0, in
1822. Work on a larger version, which was supposed to enable larger
calculations, was funded by the British government. Unfortunately, this
did not materialize due to the manufacturing limitations of the time. It
took 20 years and large amounts until the project was abandoned. The
Difference Engine 1 was never completed.</p>

<p>During this time, Babbage started thinking about a general-purpose
computer, the Analytical Engine. The Analytical Engine would include an
arithmetic logic unit, control flow, and memory - components of modern
electronic computers. The programming language resembled modern day
assembly languages and would have been fed to the computer through punch
cards. This machine was never built.</p>

<p>Even though the physical Analytical Engine did not materialize, several
programs were created for it, both by Babbage and Ada Lovelace
(1815-1852). Ada published the first algorithm for the Analytical
Engine, used to compute Bernoulli numbers, and is regarded as the first
programmer.</p>

<h2>The foundational crisis of mathematics</h2>

<p>At the beginning of the 20th century, mathematicians were looking for a
proper foundation for mathematics: a set of axioms from which all
theorems could be derived.</p>

<p>David Hilbert (1862-1943) put forward 23 problems in 1900, which heavily
influenced the direction of mathematics research in the 20th century.
Some of the problems have since been solved, others, like the famous
Riemann hypothesis (problem 8), are still unresolved.</p>

<p>The 2nd problem, directly tying into the foundational crisis, was to
prove that the axioms of arithmetic are consistent (meaning no
contradictions can arise as theorems are derived from the axioms).</p>

<p>Alfred North Whitehead (1861-1947) and Bertrand Russell (1872-1970)
start working on the Principia Mathematica. 3 volumes are published in
1910, 1912, and 1913. Starting with a minimum set of primitive notions,
axioms, and inference rules, they deduce theorems pertaining to logic,
arithmetic, set theory and so on. Famously, the proof that 1+1=2 appears
on page 379 of volume 1.</p>

<p><img src="https://vladris.com/blog/2022/02/12/proof.png" alt="image"/></p>

<p>Kurt GÃ¶del (1906-1978) proves, with his incompleteness theorem (1930),
that a formal system powerful enough to describe arithmetic cannot be
both consistent and complete. In other words, starting from a set of
axioms, if these are consistent (no contradictions can be derived), they
cannot be complete (there will be true statements that cannot be derived
from these axioms).</p>

<p>Building upon this work, in 1933, GÃ¶del develops general recursive
functions as a model of computability (more on this later).</p>

<h2>Entscheidungsproblem and models of computability</h2>

<p>David Hilbert proposes another challenge in 1928: the decision problem.
The problem asks for an algorithm that takes a statement as an input and
decides whether the statement is provable within the considered set of
axioms. Note that GÃ¶del's incompleteness theorem shows that some true
statements cannot be proved from a consistent set of axioms. That
doesn't mean there isn't an algorithm that can decide whether a
statement is provable or not. Hilbert believed such an algorithm exists.</p>

<p>Alonzo Church (1903-1995) develops lambda calculus as a model of
computation that uses function abstraction, application, and variable
binding and substitution. Church's Theorem (1936) provides a negative
answer to the decision problem, based on lambda calculus. He shows there
is no computable function that can decide whether two lambda expressions
are equivalent.</p>

<p>During the same time, Alan Turing (1912-1954) develops another model of
computation: the Turing machine. This is an abstract computer consisting
of an infinite tape of cells, a head that can read from a cell, write to
a cell, and move left or right over the tape, and a set of rules which
direct the head based on the read symbol and the current state of the
machine. Turing also provides a negative answer to the decision problem
during the same year as Church (1936), based on Turing machines: he
shows that there is no general method to decide whether any given Turing
machine halts or not (the halting problem).</p>

<h2>Universal computability and Turing completeness</h2>

<p>These are remarkable results: we now have proof that some problems are
incomputable. More than that, we know that a Turing machine can compute
anything that is computable.</p>

<p>The Church-Turing thesis shows that lambda calculus can be used to
simulate a Turing machine. That means that lambda calculus can compute
anything that a Turing machine can compute, thus the two systems have
the same computability power.</p>

<p>In general, if a system can be used to simulate a Turing machine, this
makes it <em>Turing complete</em>, meaning capable of computing anything that
is computable.</p>

<p>GÃ¶del's general recursive functions are also shown to be an equivalent
model of computation (these are the functions that Turing machines can
compute).</p>

<p>We have 3 quite different approaches to universal computability: general
recursive functions, lambda calculus, and Turing machines. These turn
out to all be equivalent in terms of what is possible to compute.</p>

<p>Turing machines, with their simple definition, are easy to simulate,
thus making Turing completeness the preferred way of proving that a
system is capable of universal computation.</p>
]]></description>
      <pubDate>Sat, 12 Feb 2022 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/12/30/timsort.html</link>
      <guid>https://vladris.com/blog/2021/12/30/timsort.html</guid>
      <title><![CDATA[Timsort]]></title>
      <description><![CDATA[<h1>Timsort</h1>

<p>I wrote before about the inherent complexity of the real world and how
software that behaves well in the real world must necessarily take on
some complexity (<a href="https://vladris.com/blog/2020/01/19/time-and-complexity.html">Time and
Complexity</a>).
A lot of the software engineering best practices try to reduce or
eliminate the <em>accidental complexity</em> of large systems (making things
more complicated than they should be). But we don't live in a perfect
world, so modeling it using software requires some <em>inherent complexity</em>
in the software, to reflect reality. One of the algorithms which
perfectly illustrates this is the Timsort sorting algorithm.</p>

<p>Timsort is an algorithm developed by Tim Peters in 2002 to replace
Python's previous sorting algorithm. It has since been adopted
inJava's OpenJDK, the V8 JavaScript engine, and the Swift and Rust
languages. This is a testament that Timsort is a performant sort.</p>

<p>Timsort is a <em>stable sorting algorithm</em>, which means it will never
changes the relative order of equal elements. This is an important
property in certain situations. This is not important when sorting
numbers, but becomes important when sorting objects with custom
comparisons.</p>

<p>But in 2002 we already had plenty of well known sorting algorithms which
were quite efficient. How did Timsort manage to outperform these?</p>

<h2>Merging Runs</h2>

<p>The key insight of Timsort is that in the real world, many lists of
elements that require sorting contain subsequences of elements that are
already sorted. These are called <em>runs</em> and tend to appear naturally.
For example, in the list <code>[5, 2, 3, 4, 9, 1, 6, 8, 10, 7]</code> we have two
runs: <code>[2, 3, 4]</code> and <code>[1, 6, 8, 10]</code>.</p>

<p>If we know runs will show up more often than not in our input, how can
we best leverage this to our advantage, and avoid extraneous comparisons
and data movement?</p>

<p>Timsort starts by finding the minimum <q>accepted</q> run length for a
given input. This doesn't have anything to do with the content of the
input, rather it is a function of the size of the input. More on this
later.</p>

<p>Then we do a single pass over the array and identify consecutive runs.
If the next <em>minimum accepted run length</em> elements are not already
sorted (they don't form a run), we sort them using insertion sort (so
they do end up as a run). We push these runs on a stack, then we then
merge pairs of them until we end up with a single run, which is our
sorted list.</p>

<h2>A Simple Implementation</h2>

<p>Let's start with a simple sketch implementation. We'll use Python
since it is expressive and it makes it easier to focus on the algorithm
rather than syntax around it.</p>
<div class="highlight"><pre><span/><span class="n">MIN_MERGE</span> <span class="o">=</span> <span class="mi">4</span>

<span class="k">def</span><span class="w"> </span><span class="nf">sort</span><span class="p">(</span><span class="n">arr</span><span class="p">):</span> 
    <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span> 
    <span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">nRemaining</span> <span class="o">=</span> <span class="n">hi</span>
    <span class="n">minRun</span> <span class="o">=</span> <span class="n">MIN_MERGE</span>

    <span class="k">while</span> <span class="n">nRemaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">runLen</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">nRemaining</span><span class="p">,</span> <span class="n">minRun</span><span class="p">)</span>
        <span class="n">insertionSort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">runLen</span><span class="p">)</span>
        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">lo</span><span class="p">,</span> <span class="n">runLen</span><span class="p">))</span>

        <span class="n">lo</span> <span class="o">+=</span> <span class="n">runLen</span>
        <span class="n">nRemaining</span> <span class="o">-=</span> <span class="n">runLen</span>

    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">base2</span><span class="p">,</span> <span class="n">len2</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">merge</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">base1</span><span class="p">,</span> <span class="n">base2</span><span class="p">,</span> <span class="n">base2</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>
        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">+</span> <span class="n">len2</span><span class="p">))</span>
</pre></div>

<p>First, we initialize a few variables:</p>
<div class="highlight"><pre><span/><span class="n">lo</span><span class="p">,</span> <span class="n">hi</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span> 
<span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">nRemaining</span> <span class="o">=</span> <span class="n">hi</span>
<span class="n">minRun</span> <span class="o">=</span> <span class="n">MIN_MERGE</span>
</pre></div>

<p><code>MIN_MERGE</code> represents the minimum number of elements we want to merge,
and is a constant. We'll talk more about this once we look at some
optimizations later on.</p>

<p><code>lo</code> and <code>hi</code> represent the range in the array we will operate on. Note
ranges are always half-open (<code>arr[lo]</code> included, <code>arr[hi]</code> excluded,
potentially out of bounds). <code>stack</code> is the run stack, <code>nRemaining</code> is
the number of elements we still need to process. <code>minRun</code> is the minimum
run length. For this first iteration, we'll just use <code>MIN_MERGE</code>.</p>

<p>Next, we traverse the array and come up with our runs:</p>
<div class="highlight"><pre><span/><span class="k">while</span> <span class="n">nRemaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">runLen</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">nRemaining</span><span class="p">,</span> <span class="n">minRun</span><span class="p">)</span>
        <span class="n">insertionSort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">runLen</span><span class="p">)</span>
        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">lo</span><span class="p">,</span> <span class="n">runLen</span><span class="p">))</span>

        <span class="n">lo</span> <span class="o">+=</span> <span class="n">runLen</span>
        <span class="n">nRemaining</span> <span class="o">-=</span> <span class="n">runLen</span>
</pre></div>

<p>Our run in this case will be the minimum between <code>minRun</code> and the
remaining elements of the array (so for the final run, we don't go out
of bounds). We sort the run using <code>insertionSort</code>, then we push the run
start index and length onto the stack. We advance <code>lo</code> by the length of
the run and we similarly decrement <code>nRemaining</code>, the number of elements
still to be processed.</p>

<p>Next, we merge the runs:</p>
<div class="highlight"><pre><span/><span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
    <span class="n">base2</span><span class="p">,</span> <span class="n">len2</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
    <span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
    <span class="n">merge</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">base1</span><span class="p">,</span> <span class="n">base2</span><span class="p">,</span> <span class="n">base2</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>
    <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">+</span> <span class="n">len2</span><span class="p">))</span>
</pre></div>

<p>We pop 2 runs from the top of the stack, merge them, and push the new
run back onto the stack. With this basic implementation, a stack is
technically not really needed, but I'm trying to preserve the general
shape of the optimized solution.</p>

<p>We called a couple of helper functions: <code>insertionSort</code> and <code>merge</code>.
Here is <code>insertionSort</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">insertionSort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">):</span> 
    <span class="n">i</span> <span class="o">=</span> <span class="n">lo</span> <span class="o">+</span> <span class="mi">1</span>

    <span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">hi</span><span class="p">:</span>
        <span class="n">elem</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
        <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span>

        <span class="k">while</span> <span class="n">elem</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="ow">and</span> <span class="n">j</span> <span class="o">&gt;=</span> <span class="n">lo</span><span class="p">:</span>
        <span class="n">j</span> <span class="o">-=</span> <span class="mi">1</span>

        <span class="n">arr</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
        <span class="n">arr</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">elem</span><span class="p">)</span>

        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>

<p><a href="https://en.wikipedia.org/wiki/Insertion_sort">Insertion sort</a> traverses
the array from the lower bound + 1 to the higher bound and maintains the
invariant that all elements preceding <code>i</code> are sorted. So for any element
<code>arr[i]</code>, we find a spot <code>j</code> in the range <code>[lo, i)</code> where this element
should fit. We then insert it there and shift the remaining elements in
<code>[j + 1, i)</code> one spot to the right. Note this algorithm is quite
inefficient on large data sets, but performs well on small inputs.</p>

<p>Our merge algorithm is:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">merge</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">hi</span><span class="p">):</span>
    <span class="n">t</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">lo</span><span class="p">:</span><span class="n">mid</span><span class="p">]</span>
    <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="n">lo</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="mi">0</span>

    <span class="k">while</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span> <span class="ow">and</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">hi</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
            <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
            <span class="n">k</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
            <span class="n">j</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">hi</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">:</span><span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">]</span>
</pre></div>

<p>We are merging the consecutive (sorted) ranges <code>[lo, mid)</code> and
<code>[mid, hi)</code>. One way to do this (which our implementation uses), is to
copy <code>[lo, mid)</code> to a temporary buffer <code>t</code>. We then traverse the
<code>[mid, hi)</code> range with <code>j</code> and the buffer with <code>k</code>. We pick the smallest
of <code>t[k]</code> and <code>arr[j]</code> to insert at <code>arr[i]</code> (incrementing the
corresponding index), then we increment <code>i</code>. At some point, either <code>j</code>
or <code>k</code> reaches the end. If <code>j</code> makes it to the end first, it means we
still have some elements in <code>t</code> we need to copy over. If <code>k</code> makes it to
the end first, we don't need to do anything: the remaining elements in
<code>[j, hi)</code> are where they are supposed to be.</p>

<p>We now have a full implementation of a very simple Timsort. If we run it
on the <code>[5, 2, 3, 4, 9, 1, 6, 8, 10, 7]</code> input, the following steps take
place:</p>

<ul>
<li>We pick up the first run, <code>[5, 2, 3, 4]</code> and sort it using
<code>insertionSort</code>. This becomes <code>[2, 3, 4, 5]</code>. We push its start
index and length on the stack (<code>(0, 4)</code>).</li>
<li>We next take <code>[9, 1, 6, 8]</code>, sort it to <code>[1, 6, 8, 9]</code>, and push
<code>(4, 4)</code> on the stack.</li>
<li>Finally, we only have <code>[10, 7]</code>. We sort this short run to <code>[7, 10]</code>
and push <code>(6, 2)</code> on the stack.</li>
</ul>

<p>Note all our sorting happens in-place, so by now the whole input became
<code>[2, 3, 4, 5, 1, 6, 8, 9, 7, 10]</code>. We then proceed to merge runs from
the top of the stack:</p>

<ul>
<li>First, we merge <code>[1, 6, 8, 9]</code> with <code>[7, 10</code>, which yields
<code>[1, 6, 7, 8, 9, 10]</code>. We pop the two runs from the stack and push
<code>(4, 6)</code>, the index and length of this new run.</li>
<li>Next, we merge <code>[2, 3, 4, 5]</code> with <code>[1, 6, 7, 8, 9, 10]</code>, and update
the stack accordingly. At this point, we only have 1 run on the
stack (<code>[0, 10)</code>). We are done.</li>
</ul>

<h2>Some Optimizations</h2>

<p>So far, we haven't relied that much on the fact that our input might be
naturally partially sorted. Instead of simply calling <code>insertionSort</code> on
<code>minRun</code> elements, we can actually check whether elements are already
ordered. If they are, we don't need to do anything with them. Even
better, if the run of elements is longer than <code>minRun</code>, we keep going.</p>

<p>Elements might also come naturally sorted in descending order, while we
are sorting in ascending order. No problem: we can take a range of
elements coming in descending order and reverse it to produce a run in
ascending order. Let's call this function <code>countRunAndMakeAscending</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">countRunAndMakeAscending</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">):</span>
    <span class="n">runHi</span> <span class="o">=</span> <span class="n">lo</span> <span class="o">+</span> <span class="mi">1</span>
    <span class="k">if</span> <span class="n">runHi</span> <span class="o">==</span> <span class="n">hi</span><span class="p">:</span>
        <span class="k">return</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">arr</span><span class="p">[</span><span class="n">lo</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">runHi</span><span class="p">]:</span> <span class="c1"># Descending run</span>
        <span class="k">while</span> <span class="n">runHi</span> <span class="o">&lt;</span> <span class="n">hi</span> <span class="ow">and</span> <span class="n">arr</span><span class="p">[</span><span class="n">runHi</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">runHi</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]:</span>
            <span class="n">runHi</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">reverseRange</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">runHi</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span> <span class="c1"># Ascending run</span>
        <span class="k">while</span> <span class="n">runHi</span> <span class="o">&lt;</span> <span class="n">hi</span> <span class="ow">and</span> <span class="n">arr</span><span class="p">[</span><span class="n">runHi</span><span class="p">]</span> <span class="o">&gt;=</span> <span class="n">arr</span><span class="p">[</span><span class="n">runHi</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]:</span>
            <span class="n">runHi</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="n">runHi</span> <span class="o">-</span> <span class="n">lo</span>
</pre></div>

<p>We return the length of the run starting from <code>lo</code>, going to at most
<code>hi - 1</code>. If we have a natural descending run, we reverse the range
before returning. Here is <code>reverseRange</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">reverseRange</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">):</span>
    <span class="n">hi</span> <span class="o">-=</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="n">lo</span> <span class="o">&lt;</span> <span class="n">hi</span><span class="p">:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">lo</span><span class="p">],</span> <span class="n">arr</span><span class="p">[</span><span class="n">hi</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">hi</span><span class="p">],</span> <span class="n">arr</span><span class="p">[</span><span class="n">lo</span><span class="p">]</span>
        <span class="n">lo</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">hi</span> <span class="o">-=</span> <span class="mi">1</span>
</pre></div>

<p>We can't get rid of sorting though: we might have worst-case scenario
cases with very small runs, in which case we still need a range of at
least <code>minRun</code> size. Based on the result of <code>countRunAndMarkAscending</code>,
if it is smaller than <code>minRun</code>, we will <q>force</q> a few more elements
into the run and sort it. Our new implementation looks like this:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">sort</span><span class="p">(</span><span class="n">arr</span><span class="p">):</span> 
    <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span> 
    <span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">nRemaining</span> <span class="o">=</span> <span class="n">hi</span>
    <span class="n">minRun</span> <span class="o">=</span> <span class="n">MIN_MERGE</span>

    <span class="k">while</span> <span class="n">nRemaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">runLen</span> <span class="o">=</span> <span class="n">countRunAndMakeAscending</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">runLen</span> <span class="o">&lt;</span> <span class="n">minRun</span><span class="p">:</span>
            <span class="n">force</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">nRemaining</span><span class="p">,</span> <span class="n">minRun</span><span class="p">)</span>
            <span class="n">insertionSort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">force</span><span class="p">)</span>
            <span class="n">runLen</span> <span class="o">=</span> <span class="n">force</span>

        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">lo</span><span class="p">,</span> <span class="n">runLen</span><span class="p">))</span>

        <span class="n">lo</span> <span class="o">+=</span> <span class="n">runLen</span>
        <span class="n">nRemaining</span> <span class="o">-=</span> <span class="n">runLen</span>

    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">base2</span><span class="p">,</span> <span class="n">len2</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">merge</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">base1</span><span class="p">,</span> <span class="n">base2</span><span class="p">,</span> <span class="n">base2</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>
        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">+</span> <span class="n">len2</span><span class="p">))</span>
</pre></div>

<p>Highlighting the changed part:</p>
<div class="highlight"><pre><span/><span class="n">runLen</span> <span class="o">=</span> <span class="n">countRunAndMakeAscending</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">)</span>

<span class="k">if</span> <span class="n">runLen</span> <span class="o">&lt;</span> <span class="n">minRun</span><span class="p">:</span>
    <span class="n">force</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">nRemaining</span><span class="p">,</span> <span class="n">minRun</span><span class="p">)</span>
    <span class="n">insertionSort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">force</span><span class="p">)</span>
    <span class="n">runLen</span> <span class="o">=</span> <span class="n">force</span>
</pre></div>

<p>Instead of simply taking the next <code>minRun</code> elements, we try to find a
run. If the run we find is smaller than <code>minRun</code>, we force it to be
<code>minRun</code> by insertion-sorting into it more elements. If it is larger
than or equal to <code>minRun</code> on the other hand, we don't have to do any
sorting.</p>

<p>It gets better: now we know after calling <code>countRunAndMakeAscending</code>
that the range <code>[lo, lo + runLen)</code> is already sorted. We can hint this
to our sorting function and have it start sorting only from
<code>lo + runLen</code>. We can update <code>insertionSort</code> to take a hint of where to
start from:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">insertionSort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">,</span> <span class="n">start</span><span class="p">):</span> 
    <span class="k">if</span> <span class="n">start</span> <span class="o">==</span> <span class="n">lo</span><span class="p">:</span>
        <span class="n">start</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">while</span> <span class="n">start</span> <span class="o">&lt;</span> <span class="n">hi</span><span class="p">:</span>
        <span class="n">elem</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">start</span><span class="p">]</span>
        <span class="n">j</span> <span class="o">=</span> <span class="n">start</span> <span class="o">-</span> <span class="mi">1</span>

        <span class="k">while</span> <span class="n">elem</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="ow">and</span> <span class="n">j</span> <span class="o">&gt;=</span> <span class="n">lo</span><span class="p">:</span>
        <span class="n">j</span> <span class="o">-=</span> <span class="mi">1</span>

        <span class="n">arr</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">start</span><span class="p">)</span>
        <span class="n">arr</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">elem</span><span class="p">)</span>

        <span class="n">start</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>

<p>This version is very similar to our previous one. Instead of using a
local <code>i</code> variable to iterate over the range <code>[lo + 1, hi)</code>, we just use
<code>start</code>. If <code>start</code> is <code>lo</code>, we increment it before the loop (just like
we used to initialize <code>i</code> to <code>lo + 1</code>).</p>

<p>We can now pass this hint in from our main function:</p>
<div class="highlight"><pre><span/><span class="k">while</span> <span class="n">nRemaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
    <span class="n">runLen</span> <span class="o">=</span> <span class="n">countRunAndMakeAscending</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">runLen</span> <span class="o">&lt;</span> <span class="n">minRun</span><span class="p">:</span>
        <span class="n">force</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">nRemaining</span><span class="p">,</span> <span class="n">minRun</span><span class="p">)</span>
        <span class="n">insertionSort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">force</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">runLen</span><span class="p">)</span>
        <span class="n">runLen</span> <span class="o">=</span> <span class="n">force</span>
</pre></div>

<p>At this point, we're starting to get a lot of value from naturally
sorted runs: we either don't do any sorting, or just sort at most
<code>minRun - runLen</code> elements into the range.</p>

<p>A further optimization for sorting: we can replace insertion sort with
binary sort. Binary sort works much like insertion sort, but instead of
checking where element <code>i</code> fits into <code>[lo, i)</code> by comparing it with
<code>i - 1</code>, then <code>i - 2</code> and so on, it relies on the fact that <code>[lo, i)</code> is
already sorted and performs a binary search to find the right spot. Here
is an implementation, which also takes a <code>start</code> hint:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">binarySort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">,</span> <span class="n">start</span><span class="p">):</span>
    <span class="k">if</span> <span class="n">start</span> <span class="o">==</span> <span class="n">lo</span><span class="p">:</span>
        <span class="n">start</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">while</span> <span class="n">start</span> <span class="o">&lt;</span> <span class="n">hi</span><span class="p">:</span>
        <span class="n">pivot</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">start</span><span class="p">]</span>
        <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="n">lo</span><span class="p">,</span> <span class="n">start</span>

        <span class="k">while</span> <span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">:</span>
            <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">left</span> <span class="o">+</span> <span class="n">right</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>

            <span class="k">if</span> <span class="n">pivot</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">]:</span>
                <span class="n">right</span> <span class="o">=</span> <span class="n">mid</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">left</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span>

        <span class="n">arr</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="n">start</span><span class="p">)</span>
        <span class="n">arr</span><span class="o">.</span><span class="n">insert</span><span class="p">(</span><span class="n">left</span><span class="p">,</span> <span class="n">pivot</span><span class="p">)</span>

        <span class="n">start</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>

<p>Our main function now looks like this:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">sort</span><span class="p">(</span><span class="n">arr</span><span class="p">):</span> 
    <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span> 
    <span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">nRemaining</span> <span class="o">=</span> <span class="n">hi</span>
    <span class="n">minRun</span> <span class="o">=</span> <span class="n">MIN_MERGE</span>

    <span class="k">while</span> <span class="n">nRemaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">runLen</span> <span class="o">=</span> <span class="n">countRunAndMakeAscending</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">runLen</span> <span class="o">&lt;</span> <span class="n">minRun</span><span class="p">:</span>
            <span class="n">force</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">nRemaining</span><span class="p">,</span> <span class="n">minRun</span><span class="p">)</span>
            <span class="n">binarySort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">force</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">runLen</span><span class="p">)</span>
            <span class="n">runLen</span> <span class="o">=</span> <span class="n">force</span>

        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">lo</span><span class="p">,</span> <span class="n">runLen</span><span class="p">))</span>

        <span class="n">lo</span> <span class="o">+=</span> <span class="n">runLen</span>
        <span class="n">nRemaining</span> <span class="o">-=</span> <span class="n">runLen</span>

    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">base2</span><span class="p">,</span> <span class="n">len2</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">=</span> <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>
        <span class="n">merge</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">base1</span><span class="p">,</span> <span class="n">base2</span><span class="p">,</span> <span class="n">base2</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>
        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">+</span> <span class="n">len2</span><span class="p">))</span>
</pre></div>

<h2>Balanced Merges</h2>

<p>Another key optimization of Timsort is trying as much as possible to
merge runs of balanced sizes. The closer the size, the better average
performance as a combination of additional space required and number of
operations.</p>

<p>So far we just pushed everything onto a stack, then merged the top 2
elements of the stack until we ended up with a single run. We actually
want to do something a bit different: we want our stack to maintain a
couple of invariants:</p>

<ol>
<li> <code>stack[i - 1][1] &gt; stack[i][1] + stack[i + 1][1]</code> - the length of a
run needs to be larger than the sum of the lengths of the following
runs.</li>
<li> <code>stack[i][1] &gt; stack[i + 1][1]</code> - the length of a run needs to be
larger than the following run.</li>
</ol>

<p>When pushing a new index and run length tuple onto the stack, we check
if the invariant still holds. If it doesn't, we merge <code>stack[i]</code> with
the smallest of <code>stack[i - 1]</code>, <code>stack[i + 1]</code> and recheck. We continue
merging until the invariants are re-established. Let's call this
function <code>mergeCollapse</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">mergeCollapse</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">):</span>
    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span>
        <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">])</span> <span class="ow">or</span> \
        <span class="p">(</span><span class="n">n</span> <span class="o">&gt;</span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;=</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]):</span>
        <span class="k">if</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
            <span class="n">n</span> <span class="o">-=</span> <span class="mi">1</span>
        <span class="k">elif</span> <span class="n">n</span> <span class="o">&lt;</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
            <span class="k">break</span>

        <span class="n">mergeAt</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
</pre></div>

<p>We start from the top of the stack - 2. If <code>n &gt; 0</code> and the invariant
doesn't hold for <code>stack[n - 1]</code>, <code>stack[n]</code>, and <code>stack[n + 1]</code> or if
<code>n &gt; 1</code> and the invariant doesn't hold for <code>stack[n - 2]</code>,
<code>stack[n - 1]</code> and <code>stack[n]</code>, we need to merge. We decide whether we
want to merge <code>stack[n]</code> with <code>stack[n + 1]</code> or <code>stack[n - 1]</code> with
<code>stack[n]</code> depending on which one is smallest (if <code>stack[n - 1]</code> is
smaller, then we decrement <code>n</code> to trigger the merge at <code>n - 1</code>.</p>

<p>If the invariant holds, we check for the other invariant:
<code>stack[n][1] &gt; stack[n + 1][1]</code>. If this second invariant holds, we're
done and we can break out of the loop (we do the same if we ran out of
elements). If not, we trigger a merge by calling <code>mergeAt</code> and repeat
until we either merge everything or the invariant is reestablished.</p>

<p>We start by checking only the top few elements of the stack, since we
expect the rest of the stack to hold the invariants. We only call this
function when we push a new run on the stack, in which case we need to
ensure we merge as needed.</p>

<p>Let's take a look at <code>mergeAt</code>. This function simply merges the runs at
positions <code>n</code> and <code>n + 1</code> on the stack:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">mergeAt</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
    <span class="k">assert</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span> <span class="ow">or</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">-</span> <span class="mi">3</span>

    <span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
    <span class="n">base2</span><span class="p">,</span> <span class="n">len2</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>

    <span class="n">stack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>

    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">-</span> <span class="mi">3</span><span class="p">:</span>
        <span class="n">stack</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
    <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>

    <span class="n">merge</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">base1</span><span class="p">,</span> <span class="n">base2</span><span class="p">,</span> <span class="n">base2</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>
</pre></div>

<p>Remember we only ever merge either the second from top and top runs or
the third from top and second from top runs. So <code>i</code> should be either
<code>len(stack) - 2</code> or <code>len(stack) - 3</code>. We get the first element and run
length for the two runs and update the stack: <code>stack[i]</code> starts at the
same position but will now have the length of both unmerged runs. If we
are merging <code>stack[-3]</code> with <code>stack[-2]</code>, we need to copy <code>stack[-1]</code>
(top of the stack) to <code>stack[-2]</code> (second to top). Finally, we pop the
top of the stack. At this point, the stack is updated. We call <code>merge</code>
on the two runs to update <code>arr</code> too.</p>

<p>We can now maintain a healthy balance for merges. Remember, the whole
reason for this is to aim to always merge runs similar in size.</p>

<p>Of course, once we are done pushing everything on the stack, we still
need to force merging to finish our sort. We'll do this with
<code>mergeForceCollapse</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">mergeForceCollapse</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">):</span>
    <span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">&gt;</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">n</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">-</span> <span class="mi">2</span>
        <span class="k">if</span> <span class="n">n</span> <span class="o">&gt;</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">stack</span><span class="p">[</span><span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]:</span>
            <span class="n">n</span> <span class="o">-=</span> <span class="mi">1</span>

        <span class="n">mergeAt</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
</pre></div>

<p>This function again merges the second from the top run with the smallest
of third from the top or top. It continues until all runs are merged
into one. Our updates <code>sort</code> looks like this:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">sort</span><span class="p">(</span><span class="n">arr</span><span class="p">):</span> 
    <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span> 
    <span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">nRemaining</span> <span class="o">=</span> <span class="n">hi</span>
    <span class="n">minRun</span> <span class="o">=</span> <span class="n">MIN_MERGE</span>

    <span class="k">while</span> <span class="n">nRemaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">runLen</span> <span class="o">=</span> <span class="n">countRunAndMakeAscending</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">)</span>

        <span class="k">if</span> <span class="n">runLen</span> <span class="o">&lt;</span> <span class="n">minRun</span><span class="p">:</span>
            <span class="n">force</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">nRemaining</span><span class="p">,</span> <span class="n">minRun</span><span class="p">)</span>
            <span class="n">binarySort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">force</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">runLen</span><span class="p">)</span>
            <span class="n">runLen</span> <span class="o">=</span> <span class="n">force</span>

        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">lo</span><span class="p">,</span> <span class="n">runLen</span><span class="p">))</span>
        <span class="n">mergeCollapse</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">)</span>

        <span class="n">lo</span> <span class="o">+=</span> <span class="n">runLen</span>
        <span class="n">nRemaining</span> <span class="o">-=</span> <span class="n">runLen</span>

    <span class="n">mergeForceCollapse</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">)</span>
</pre></div>

<p>Instead of pushing everything onto the stack and merging everything at
the end, we now call <code>mergeCollapse</code> after each push to keep the runs
balanced. At the end, we call <code>mergeForceCollapse</code> to force-merge the
stack.</p>

<h2>Run Lengths</h2>

<p>We used a constant minimum run length so far, but mentioned earlier that
it is in fact determined as a function of the size of the input. We will
determine this with <code>minRunLength</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">minRunLength</span><span class="p">(</span><span class="n">n</span><span class="p">):</span> 
    <span class="n">r</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">while</span> <span class="n">n</span> <span class="o">&gt;=</span> <span class="n">MIN_MERGE</span><span class="p">:</span> 
        <span class="n">r</span> <span class="o">|=</span> <span class="n">n</span> <span class="o">&amp;</span> <span class="mi">1</span>
        <span class="n">n</span> <span class="o">&gt;&gt;=</span> <span class="mi">1</span>
    <span class="k">return</span> <span class="n">n</span> <span class="o">+</span> <span class="n">r</span>
</pre></div>

<p>This function takes the length of the input and does the following:</p>

<ul>
<li>If <code>n</code> is smaller than <code>MIN_MERGE</code>, returns <code>n</code> - the input size is
too small to use complicated optimizations on.</li>
<li>If <code>n</code> is a power of 2, the algorithm will return <code>MIN_MERGE / 2</code>.
Note: <code>MIN_MERGE</code> is also a power of 2. In our initial sketch we set
it to 4, but in practice this is usually 32 or 64.</li>
<li>Otherwise return a number <code>k</code> between <code>MIN_MERGE / 2</code> and
<code>MIN_MERGE</code> so that <code>n / k</code> is close to but strictly less than a
power of 2.</li>
</ul>

<p>It does this by shifting <code>n</code> one bit to the right until it is less than
<code>MIN_MERGE</code>. In case any shifted bit is 1, it means <code>n</code> is not a power
of 2. In that case, we set <code>r</code> to 1 and return <code>n + 1</code>.</p>

<p>The reason we do all of this work is to again strive to keep merges
balanced. If we get an input like 2048 and our MIN_MERGE is 64, we get
back 32. That means that, if we don't have any great runs in our input,
we end up with 64 runs, each of length 32. We saw in the previous
section how we balance the stack. Consider we're pushing these runs
onto the stack:</p>

<ul>
<li>We push the run <code>(0, 32)</code> on the stack (first 32 elements).</li>
<li>We push the run <code>(32, 32)</code> on the stack (next 32 elements).</li>
<li>This triggers a merge since the run <code>(0, 32)</code> is not greater than
the run <code>(32, 32)</code>. The stack becomes <code>(0, 64)</code>.</li>
<li>We push the run <code>(64, 32)</code> on the stack (next 32 elements).</li>
<li>We push the run <code>(96, 32)</code> on the stack (next 32 elements).</li>
<li>This again triggers a merge, since the length of the run
<code>(0, 64)</code> (64) is not greater than the length of the next two runs,
both of which are 32. The run <code>(64, 32)</code> gets merged with the
smaller run, <code>(96, 32)</code>. The stack becomes <code>[(0, 64), (64, 64)]</code>.</li>
<li>The second invariant no longer holds: the first run is not longer
than then next one. Another merged is triggered and the stack
becomes <code>[(0, 128)]</code>.</li>
</ul>

<p>This goes on in the same fashion, and all merges end up being perfectly
balanced. This works great for powers of 2.</p>

<p>Now let's consider another case: what if the input is 2112? If we would
still use 32 as our minimum run length, we would get 66 runs of length
32. The first 64 will trigger perfectly balanced merges as before, but
then we end up with the stack <code>[(0, 2048), (2048, 32), (2080, 32)]</code>.
This collapses to <code>[(0, 2048), (2048, 64)]</code>, triggering a completely
unbalanced merge (2048 on one side and 64 on the other).</p>

<p>To keep things balanced, if our input is not a power of 2, we pick a
minimum run length that is close to but strictly less than a power of 2.
Let's update our <code>MIN_MERGE</code> to be 32, and update our <code>sort</code> to call
<code>minRunLength</code> instead of automatically setting it to <code>MIN_MERGE</code>.
We'll throw in another quick optimization: if the whole input is
smaller than <code>MIN_MERGE</code>, don't even bother with the whole thing: find
a starting run then binary sort the rest, without any merging.</p>
<div class="highlight"><pre><span/><span class="n">MIN_MERGE</span> <span class="o">=</span> <span class="mi">32</span>

<span class="k">def</span><span class="w"> </span><span class="nf">sort</span><span class="p">(</span><span class="n">arr</span><span class="p">):</span>
    <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span>
    <span class="n">stack</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">nRemaining</span> <span class="o">=</span> <span class="n">hi</span>
    <span class="k">if</span> <span class="n">nRemaining</span> <span class="o">&lt;</span> <span class="n">MIN_MERGE</span><span class="p">:</span>
        <span class="n">initRunLen</span> <span class="o">=</span> <span class="n">countRunAndMakeAscending</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">)</span>
        <span class="n">binarySort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">initRunLen</span><span class="p">)</span>
        <span class="k">return</span>
    <span class="n">minRun</span> <span class="o">=</span> <span class="n">minRunLength</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">arr</span><span class="p">))</span>
    <span class="k">while</span> <span class="n">nRemaining</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">runLen</span> <span class="o">=</span> <span class="n">countRunAndMakeAscending</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">hi</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">runLen</span> <span class="o">&lt;</span> <span class="n">minRun</span><span class="p">:</span>
            <span class="n">force</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">nRemaining</span><span class="p">,</span> <span class="n">minRun</span><span class="p">)</span>
            <span class="n">binarySort</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">force</span><span class="p">,</span> <span class="n">lo</span> <span class="o">+</span> <span class="n">runLen</span><span class="p">)</span>
            <span class="n">runLen</span> <span class="o">=</span> <span class="n">force</span>
        <span class="n">stack</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">lo</span><span class="p">,</span> <span class="n">runLen</span><span class="p">))</span>
        <span class="n">mergeCollapse</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">)</span>
        <span class="n">lo</span> <span class="o">+=</span> <span class="n">runLen</span>
        <span class="n">nRemaining</span> <span class="o">-=</span> <span class="n">runLen</span>
    <span class="n">mergeForceCollapse</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">)</span>
</pre></div>

<h2>Optimized Merging</h2>

<p>We can optimize merging further. Our initial implementation of <code>merge</code>
simply copied the first run into a buffer, then performed the merge. We
can do better than that.</p>

<p>What if the second run is smaller? Maybe we'd prefer always merging the
smaller run into the larger one. Let's look at an optimized version of
merge. First, we'll replace <code>merge</code> with two functions, <code>mergeLo</code> and
<code>mergeHi</code>. <code>mergeLo</code> will copy elements from the first run into the
temporary buffer, while <code>mergeHi</code> will copy elements from the second
run. Our original <code>merge</code> becomes <code>mergeLo</code>, and we can add a <code>mergeHi</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">mergeHi</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">hi</span><span class="p">):</span>
    <span class="n">t</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">:</span><span class="n">hi</span><span class="p">]</span>
    <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="n">hi</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">hi</span> <span class="o">-</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="n">k</span> <span class="o">&gt;=</span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">j</span> <span class="o">&gt;=</span> <span class="n">lo</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
            <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
            <span class="n">k</span> <span class="o">-=</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
            <span class="n">j</span> <span class="o">-=</span> <span class="mi">1</span>
        <span class="n">i</span> <span class="o">-=</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">k</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">lo</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
</pre></div>

<p>This is very similar with <code>merge</code>, except it copies the second (<code>mid</code> to
<code>hi</code>) run into a temporary buffer and traverses the runs and the buffer
from end to start.</p>

<p>When we trigger the merge, another optimization we can do is check
elements from the first run and see if they are smaller than the first
element in the second run. While they are smaller, we can simply ignore
them when merging - they are already in position. We do this by taking
the first element of the second run and seeing where it would fit in the
first run.</p>

<p>Similarly, elements from the end of the second run which are greater
than the last element in the first run are already in place. We don't
need to touch them. We take the last element of the first run and check
where it would fit in the first run.</p>

<p>We can use binary search for this. Note that we need two version in
order to maintain the stable property of the sort: a <code>searchLeft</code>, which
returns the first index where a new element should be inserted, and a
<code>searchRight</code>, which returns the last index. For example, if we have a
run like <code>[1, 2, 5, 5, 5, 5, 7, 8]</code> and we are looking for where to
insert another <code>5</code>, it really depends where it comes from. If it comes
from the run before this one, we need the left-most spot (before the
first <code>5</code> in the run). On the other hand, if it comes from the run after
this one, we need to place it after the last <code>5</code>. That ensures that the
relative order of elements is preserved. Here is an implementation for
<code>searchLeft</code> and <code>searchRight</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">searchLeft</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">arr</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="nb">len</span><span class="p">):</span>
    <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="n">base</span><span class="p">,</span> <span class="n">base</span> <span class="o">+</span> <span class="nb">len</span>
    <span class="k">while</span> <span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">:</span>
        <span class="n">mid</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">(</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
        <span class="k">if</span> <span class="n">key</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">]:</span>
            <span class="n">left</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">right</span> <span class="o">=</span> <span class="n">mid</span>

    <span class="k">return</span> <span class="n">left</span> <span class="o">-</span> <span class="n">base</span>

<span class="k">def</span><span class="w"> </span><span class="nf">searchRight</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">arr</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="nb">len</span><span class="p">):</span>
    <span class="n">left</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="n">base</span><span class="p">,</span> <span class="nb">len</span>

    <span class="k">while</span> <span class="n">left</span> <span class="o">&lt;</span> <span class="n">right</span><span class="p">:</span>
        <span class="n">mid</span> <span class="o">=</span> <span class="n">left</span> <span class="o">+</span> <span class="p">(</span><span class="n">right</span> <span class="o">-</span> <span class="n">left</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
        <span class="k">if</span> <span class="n">key</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">]:</span>
            <span class="n">right</span> <span class="o">=</span> <span class="n">mid</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">left</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span>

    <span class="k">return</span> <span class="n">left</span> <span class="o">-</span> <span class="n">base</span>
</pre></div>

<p>Both functions return the offset from <code>base</code> where <code>key</code> should be
inserted.</p>

<p>We can now update our <code>mergeAt</code> function with the new capabilities:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">mergeAt</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">stack</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
    <span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
    <span class="n">base2</span><span class="p">,</span> <span class="n">len2</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>

    <span class="n">stack</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">base1</span><span class="p">,</span> <span class="n">len1</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">i</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">stack</span><span class="p">)</span> <span class="o">-</span> <span class="mi">3</span><span class="p">:</span>
        <span class="n">stack</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">stack</span><span class="p">[</span><span class="n">i</span> <span class="o">+</span> <span class="mi">2</span><span class="p">]</span>
    <span class="n">stack</span><span class="o">.</span><span class="n">pop</span><span class="p">()</span>

    <span class="n">k</span> <span class="o">=</span> <span class="n">searchRight</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">base2</span><span class="p">],</span> <span class="n">arr</span><span class="p">,</span> <span class="n">base1</span><span class="p">,</span> <span class="n">len1</span><span class="p">)</span>
    <span class="n">base1</span> <span class="o">+=</span> <span class="n">k</span>
    <span class="n">len1</span> <span class="o">-=</span> <span class="n">k</span>
    <span class="k">if</span> <span class="n">len1</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="n">len2</span> <span class="o">=</span> <span class="n">searchLeft</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">base1</span> <span class="o">+</span> <span class="n">len1</span> <span class="o">-</span> <span class="mi">1</span><span class="p">],</span> <span class="n">arr</span><span class="p">,</span> <span class="n">base2</span><span class="p">,</span> <span class="n">len2</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">len2</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="k">if</span> <span class="n">len1</span> <span class="o">&gt;</span> <span class="n">len2</span><span class="p">:</span>
        <span class="n">mergeLo</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">base1</span><span class="p">,</span> <span class="n">base2</span><span class="p">,</span> <span class="n">base2</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">mergeHi</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">base1</span><span class="p">,</span> <span class="n">base2</span><span class="p">,</span> <span class="n">base2</span> <span class="o">+</span> <span class="n">len2</span><span class="p">)</span>
</pre></div>

<p>The first part stays the same: we get <code>base1</code>, <code>len1</code>, <code>base2</code>, and
<code>len2</code> and update the stack. Next, instead of merging right away, we
first search for where the first element of the second run would go into
the first run. We know the elements in <code>[base1, k)</code> won't move, so we
can remove them from the merge by moving <code>base1</code> to the right <code>k</code>
elements (we also need to update <code>len1</code>). Similarly, we search for where
the last element of the first run (<code>arr[base1 + len1 - 1]</code>) would fit
into the second run. We know all elements beyond that are already in
place, so we update <code>len2</code> to be this offset.</p>

<p>In case either of the searches exhausts a run, we simply return.
Otherwise, depending on which run is longer, we call <code>mergeLo</code> or
<code>mergeHi</code>.</p>

<h2>Galloping</h2>

<p>But wait, there's more! Binary search always performs <code>log(len + 1)</code>
comparisons where <code>len</code> is the length of the array we are searching for
regardless of where our element belongs. Galloping attempts to find the
spot faster.</p>

<p>Galloping starts by comparing the element we are searching for in array
<code>A</code> with <code>A[0]</code>, <code>A[1]</code>, <code>A[3]</code>, ... <code>A[i^2 - 1]</code>. With these
comparisons, we will end up finding a range between some
<code>A[(k - 1)^2 - 1]</code> and <code>A[k^2 - 1]</code> that would contain the element we
are searching for. We then run a binary search only within that
interval.</p>

<p>There are some tradeoffs here: on large datasets or purely random data,
binary search performs better. But on inputs which contain natural runs,
galloping tends to find things faster. Galloping also performs better
when we expect to find the interval early on. Let's look at an
implementation of <code>gallopLeft</code> as an alternative to <code>searchLeft</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">gallopLeft</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">arr</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="nb">len</span><span class="p">,</span> <span class="n">hint</span><span class="p">):</span>
    <span class="n">lastOfs</span><span class="p">,</span> <span class="n">ofs</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">key</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span><span class="p">]:</span>
        <span class="n">maxOfs</span> <span class="o">=</span> <span class="nb">len</span> <span class="o">-</span> <span class="n">hint</span>
        <span class="k">while</span> <span class="n">ofs</span> <span class="o">&lt;</span> <span class="n">maxOfs</span> <span class="ow">and</span> <span class="n">key</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span> <span class="o">+</span> <span class="n">ofs</span><span class="p">]:</span>
            <span class="n">lastOfs</span> <span class="o">=</span> <span class="n">ofs</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="p">(</span><span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">ofs</span> <span class="o">&gt;</span> <span class="n">maxOfs</span><span class="p">:</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="n">maxOfs</span>

        <span class="n">lastOfs</span> <span class="o">+=</span> <span class="n">hint</span>
        <span class="n">ofs</span> <span class="o">+=</span> <span class="n">hint</span>
    <span class="k">else</span><span class="p">:</span> <span class="c1"># key &lt;= arr[base + hint]</span>
        <span class="n">maxOfs</span> <span class="o">=</span> <span class="n">hint</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">while</span> <span class="n">ofs</span> <span class="o">&lt;</span> <span class="n">maxOfs</span> <span class="ow">and</span> <span class="n">key</span> <span class="o">&lt;=</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">ofs</span><span class="p">]:</span>
            <span class="n">lastOfs</span> <span class="o">=</span> <span class="n">ofs</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="p">(</span><span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">ofs</span> <span class="o">&gt;</span> <span class="n">maxOfs</span><span class="p">:</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="n">maxOfs</span>

        <span class="n">lastOfs</span><span class="p">,</span> <span class="n">ofs</span> <span class="o">=</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">ofs</span><span class="p">,</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">lastOfs</span>

    <span class="c1"># arr[base + lastOfs] &lt; key &lt;= arr[base + ofs]</span>
    <span class="n">lastOfs</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="n">lastOfs</span> <span class="o">&lt;</span> <span class="n">ofs</span><span class="p">:</span>
        <span class="n">mid</span> <span class="o">=</span> <span class="n">lastOfs</span> <span class="o">+</span> <span class="p">(</span><span class="n">ofs</span> <span class="o">-</span> <span class="n">lastOfs</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span>
        <span class="k">if</span> <span class="n">key</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">mid</span><span class="p">]:</span>
            <span class="n">lastOfs</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="n">mid</span>
    <span class="k">return</span> <span class="n">ofs</span>
</pre></div>

<p>We start by initializing 2 offsets: <code>lastOfs</code> and <code>ofs</code> to represent the
offsets between which we expect to find our key. Note the function also
takes a hint, so callers can provide a tentative starting place.</p>

<p>Let's go over the parts of this function:</p>
<div class="highlight"><pre><span/><span class="k">if</span> <span class="n">key</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span><span class="p">]:</span>
    <span class="n">maxOfs</span> <span class="o">=</span> <span class="nb">len</span> <span class="o">-</span> <span class="n">hint</span>
    <span class="k">while</span> <span class="n">ofs</span> <span class="o">&lt;</span> <span class="n">maxOfs</span> <span class="ow">and</span> <span class="n">key</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span> <span class="o">+</span> <span class="n">ofs</span><span class="p">]:</span>
        <span class="n">lastOfs</span> <span class="o">=</span> <span class="n">ofs</span>
        <span class="n">ofs</span> <span class="o">=</span> <span class="p">(</span><span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">ofs</span> <span class="o">&gt;</span> <span class="n">maxOfs</span><span class="p">:</span>
        <span class="n">ofs</span> <span class="o">=</span> <span class="n">maxOfs</span>

    <span class="n">lastOfs</span> <span class="o">+=</span> <span class="n">hint</span>
    <span class="n">ofs</span> <span class="o">+=</span> <span class="n">hint</span>
</pre></div>

<p>We first find the two offsets. If the key we are searching for is
greater than (right of) our starting element (<code>arr[base + hint]</code>), then
our maximum possible offset is <code>len - hint</code>. While <code>ofs</code> is hasn't
overflowed and the key is still larger than <code>arr[base + hint + ofs]</code>, we
keep updating <code>ofs</code> to be the next power of 2 minus 1. We keep track of
the previous offset in <code>lastOfs</code>. Once we're done, we add <code>hint</code> to
both offsets (we do that because we add <code>hint</code> to all indices in our
loop, but not to <code>ofs</code> since we keep it a power of 2 minus 1). If
<code>key &gt; arr[base + hint]</code> is not true, in other words, our key is left of
our starting element:</p>
<div class="highlight"><pre><span/><span class="k">else</span><span class="p">:</span> <span class="c1"># key &lt;= arr[base + hint]</span>
    <span class="n">maxOfs</span> <span class="o">=</span> <span class="n">hint</span> <span class="o">+</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="n">ofs</span> <span class="o">&lt;</span> <span class="n">maxOfs</span> <span class="ow">and</span> <span class="n">key</span> <span class="o">&lt;=</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">ofs</span><span class="p">]:</span>
        <span class="n">lastOfs</span> <span class="o">=</span> <span class="n">ofs</span>
        <span class="n">ofs</span> <span class="o">=</span> <span class="p">(</span><span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">ofs</span> <span class="o">&gt;</span> <span class="n">maxOfs</span><span class="p">:</span>
        <span class="n">ofs</span> <span class="o">=</span> <span class="n">maxOfs</span>

    <span class="n">lastOfs</span><span class="p">,</span> <span class="n">ofs</span> <span class="o">=</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">ofs</span><span class="p">,</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">lastOfs</span>
</pre></div>

<p>In this case, our maximum possible offset is <code>hint + 1</code>. We gallop
again, but now we are looking at elements left of our starting point,
<code>arr[base + hint - ofs]</code> where <code>ofs</code> keeps increasing. Once we find the
range, we update our offsets: <code>lastOfs</code> becomes <code>hint - ofs</code> and <code>ofs</code>
becomes <code>hint - lastOfs</code>. The <code>hint -</code> part is again because that is
what we actually used as indices. The swap is because we were moving
left, and we need <code>lastOfs</code> to be the one on the left, <code>ofs</code> the one on
the right.</p>

<p>We now identified the range within which we'll find our key, between
<code>arr[base + lastOfs]</code> and <code>arr[base + ofs]</code>. The last part of the
function is just a binary search within this interval.</p>

<p>The <code>gallopRight</code> function is very similar to <code>gallopLeft</code>:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">gallopRight</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">arr</span><span class="p">,</span> <span class="n">base</span><span class="p">,</span> <span class="nb">len</span><span class="p">,</span> <span class="n">hint</span><span class="p">):</span>
    <span class="n">ofs</span><span class="p">,</span> <span class="n">lastOfs</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">0</span>

    <span class="k">if</span> <span class="n">key</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span><span class="p">]:</span>
        <span class="n">maxOfs</span> <span class="o">=</span> <span class="n">hint</span> <span class="o">+</span> <span class="mi">1</span>
        <span class="k">while</span> <span class="n">ofs</span> <span class="o">&lt;</span> <span class="n">maxOfs</span> <span class="ow">and</span> <span class="n">key</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">ofs</span><span class="p">]:</span>
            <span class="n">lastOfs</span> <span class="o">=</span> <span class="n">ofs</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="p">(</span><span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">ofs</span> <span class="o">&gt;</span> <span class="n">maxOfs</span><span class="p">:</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="n">maxOfs</span>
        <span class="n">lastOfs</span><span class="p">,</span> <span class="n">ofs</span> <span class="o">=</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">ofs</span><span class="p">,</span> <span class="n">hint</span> <span class="o">-</span> <span class="n">lastOfs</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">maxOfs</span> <span class="o">=</span> <span class="nb">len</span> <span class="o">-</span> <span class="n">hint</span>
        <span class="k">while</span> <span class="n">ofs</span> <span class="o">&lt;</span> <span class="n">maxOfs</span> <span class="ow">and</span> <span class="n">key</span> <span class="o">&gt;=</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">hint</span> <span class="o">+</span> <span class="n">ofs</span><span class="p">]:</span>
            <span class="n">lastOfs</span> <span class="o">=</span> <span class="n">ofs</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="p">(</span><span class="n">ofs</span> <span class="o">&lt;&lt;</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">ofs</span> <span class="o">&gt;</span> <span class="n">maxOfs</span><span class="p">:</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="n">maxOfs</span>

        <span class="n">lastOfs</span> <span class="o">+=</span> <span class="n">hint</span><span class="p">;</span>
        <span class="n">ofs</span> <span class="o">+=</span> <span class="n">hint</span><span class="p">;</span>

    <span class="n">lastOfs</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="n">lastOfs</span> <span class="o">&lt;</span> <span class="n">ofs</span><span class="p">:</span>
        <span class="n">mid</span> <span class="o">=</span> <span class="n">lastOfs</span> <span class="o">+</span> <span class="p">((</span><span class="n">ofs</span> <span class="o">-</span> <span class="n">lastOfs</span><span class="p">)</span> <span class="o">//</span> <span class="mi">2</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">key</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">base</span> <span class="o">+</span> <span class="n">mid</span><span class="p">]:</span>
            <span class="n">ofs</span> <span class="o">=</span> <span class="n">mid</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">lastOfs</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span>
    <span class="k">return</span> <span class="n">ofs</span>
</pre></div>

<p>We won't cover this in details: the difference is here, like with
<code>searchRight</code>, we want to find the rightmost index where key belongs
instead of the leftmost one, so the algorithm changes accordingly.</p>

<p>The very neat thing about galloping is that its use isn't limited to
only when we set up the merge. We can also gallop while merging. Let's
go over <code>mergeLo</code> example, since <code>mergeHi</code> is a mirror of this.</p>

<p>In <code>mergeLo</code>, we first copy all elements from the first run to a buffer,
then we iterate over the array and at each position we copy either an
element from the buffer or one from the second run, depending on which
one is smaller. While we do this, we can keep track of how many times
the buffer or the second run <q>won</q>. If one of these wins consistently,
we can assume it will keep winning for a while longer.</p>

<p>For example, if we merge <code>[5, 6, 7, 8, 9]</code> with <code>[0, 1, 2, 3, 4]</code>, we
initialize the buffer with <code>[5, 6, 7, 8, 9]</code>, but for the next 5
comparisons, the second run wins (<code>0 &lt; 5</code>, <code>1 &lt; 5</code> ...). Now imagine
much longer runs. Instead of comparing all elements one by one, we
switch to a galloping mode:</p>

<p>We find the last spot where the next element of the second run would fit
into the buffer, and immediately copy the preceding elements of the
buffer into the array. For example, if our buffer is
<code>[12, 13, 14, 15, 17]</code> and the element we are considering from the
second run is <code>[16]</code>, we know we can copy <code>[12, 13, 14, 15]</code> into the
array. Similarly, we find the first spot the next element in the buffer
would fit into the remaining second run, and copy elements before that
from the second run to their position. The galloping mode aims to reduce
the number of comparisons and bulk copy data when possible (using a
<code>memcpy</code> equivalent where available). While galloping, we still keep
track of how many elements we were able to skip comparing individually.
If this falls below the galloping threshold, we switch back to
<q>regular</q> mode. Here is an updated <code>mergeLo</code> implementation:</p>
<div class="highlight"><pre><span/><span class="n">MIN_GALLOP</span> <span class="o">=</span> <span class="mi">7</span>
<span class="n">minGallop</span> <span class="o">=</span> <span class="n">MIN_GALLOP</span>

<span class="k">def</span><span class="w"> </span><span class="nf">mergeLo</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">hi</span><span class="p">):</span>
    <span class="n">t</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">lo</span><span class="p">:</span><span class="n">mid</span><span class="p">]</span>
    <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="n">lo</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="mi">0</span>
    <span class="k">global</span> <span class="n">minGallop</span>
    <span class="n">done</span> <span class="o">=</span> <span class="kc">False</span>

    <span class="k">while</span> <span class="ow">not</span> <span class="n">done</span><span class="p">:</span>
        <span class="n">count1</span><span class="p">,</span> <span class="n">count2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">count1</span> <span class="o">|</span> <span class="n">count2</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">minGallop</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
                <span class="n">count1</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="n">count2</span> <span class="o">=</span> <span class="mi">0</span>
                <span class="n">k</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
                <span class="n">count1</span> <span class="o">=</span> <span class="mi">0</span>
                <span class="n">count2</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="n">j</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>

            <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span> <span class="ow">or</span> <span class="n">j</span> <span class="o">==</span> <span class="n">hi</span><span class="p">:</span>
                <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                <span class="k">break</span>

        <span class="k">if</span> <span class="n">done</span><span class="p">:</span>
            <span class="k">break</span>

        <span class="k">while</span> <span class="n">count1</span> <span class="o">&gt;=</span> <span class="n">MIN_GALLOP</span> <span class="ow">or</span> <span class="n">count2</span> <span class="o">&gt;=</span> <span class="n">MIN_GALLOP</span><span class="p">:</span>
            <span class="n">count1</span> <span class="o">=</span> <span class="n">gallopRight</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">t</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span> <span class="o">-</span> <span class="n">k</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">count1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="n">count1</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">:</span><span class="n">k</span> <span class="o">+</span> <span class="n">count1</span><span class="p">]</span>
                <span class="n">i</span> <span class="o">+=</span> <span class="n">count1</span>
                <span class="n">k</span> <span class="o">+=</span> <span class="n">count1</span>
                <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">:</span>
                    <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                    <span class="k">break</span>

            <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
            <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="n">j</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="k">if</span> <span class="n">j</span> <span class="o">==</span> <span class="n">hi</span><span class="p">:</span>
                <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                <span class="k">break</span>

            <span class="n">count2</span> <span class="o">=</span> <span class="n">gallopLeft</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">arr</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">hi</span> <span class="o">-</span> <span class="n">j</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">count2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="n">count2</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">:</span><span class="n">j</span> <span class="o">+</span> <span class="n">count2</span><span class="p">]</span>
                <span class="n">i</span> <span class="o">+=</span> <span class="n">count2</span>
                <span class="n">j</span> <span class="o">+=</span> <span class="n">count2</span>
                <span class="k">if</span> <span class="n">j</span> <span class="o">==</span> <span class="n">hi</span><span class="p">:</span>
                    <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                    <span class="k">break</span>

            <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
            <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="n">k</span> <span class="o">+=</span> <span class="mi">1</span>
            <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">:</span>
                <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                <span class="k">break</span>

            <span class="n">minGallop</span> <span class="o">-=</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">minGallop</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">minGallop</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">minGallop</span> <span class="o">+=</span> <span class="mi">2</span>

    <span class="k">if</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">hi</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">:</span><span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">]</span>
</pre></div>

<p>We introduced a new <code>MIN_GALLOP</code> constant which is the threshold after
we want to start galloping. We also maintain a <code>minGallop</code> variable
across merges.</p>

<p>We have a couple of nested <code>while</code> loops, but the idea is pretty
straightforward. The first nested <code>while</code> does the normal merge but now
keeps track of how many times in the row did we end up picking an
element from the buffer:</p>
<div class="highlight"><pre><span/><span class="n">count1</span><span class="p">,</span> <span class="n">count2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="k">while</span> <span class="p">(</span><span class="n">count1</span> <span class="o">|</span> <span class="n">count2</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">minGallop</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&lt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
        <span class="n">count1</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">count2</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">k</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
        <span class="n">count1</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">count2</span> <span class="o">+=</span> <span class="mi">1</span>
        <span class="n">j</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>

    <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span> <span class="ow">or</span> <span class="n">j</span> <span class="o">==</span> <span class="n">hi</span><span class="p">:</span>
        <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="k">break</span>

<span class="k">if</span> <span class="n">done</span><span class="p">:</span>
    <span class="k">break</span>
</pre></div>

<p>Whenever we increment one counter, we set the other to 0, so at any
point, at most one of them is different than 0. We can exit the while
loop in two ways: either one of the counters reaches the gallop
threshold, or we run out of elements in one of the arrays.</p>

<p>If we ran out of elements we are done, so we break out of the outer
loop. Otherwise we are in gallop mode:</p>
<div class="highlight"><pre><span/><span class="k">while</span> <span class="n">count1</span> <span class="o">&gt;=</span> <span class="n">MIN_GALLOP</span> <span class="ow">or</span> <span class="n">count2</span> <span class="o">&gt;=</span> <span class="n">MIN_GALLOP</span><span class="p">:</span>
    <span class="n">count1</span> <span class="o">=</span> <span class="n">gallopRight</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">t</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span> <span class="o">-</span> <span class="n">k</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">count1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="n">count1</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">:</span><span class="n">k</span> <span class="o">+</span> <span class="n">count1</span><span class="p">]</span>
        <span class="n">i</span> <span class="o">+=</span> <span class="n">count1</span>
        <span class="n">k</span> <span class="o">+=</span> <span class="n">count1</span>
        <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">:</span>
            <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
            <span class="k">break</span>

    <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="n">j</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">if</span> <span class="n">j</span> <span class="o">==</span> <span class="n">hi</span><span class="p">:</span>
        <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="k">break</span>

    <span class="n">count2</span> <span class="o">=</span> <span class="n">gallopLeft</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">arr</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">hi</span> <span class="o">-</span> <span class="n">j</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
    <span class="k">if</span> <span class="n">count2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="n">count2</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">:</span><span class="n">j</span> <span class="o">+</span> <span class="n">count2</span><span class="p">]</span>
        <span class="n">i</span> <span class="o">+=</span> <span class="n">count2</span>
        <span class="n">j</span> <span class="o">+=</span> <span class="n">count2</span>
        <span class="k">if</span> <span class="n">j</span> <span class="o">==</span> <span class="n">hi</span><span class="p">:</span>
            <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
            <span class="k">break</span>

    <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
    <span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="n">k</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">:</span>
        <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
        <span class="k">break</span>

    <span class="n">minGallop</span> <span class="o">-=</span> <span class="mi">1</span>

<span class="k">if</span> <span class="n">minGallop</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
    <span class="n">minGallop</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">minGallop</span> <span class="o">+=</span> <span class="mi">2</span>
</pre></div>

<p>We first try to find where the next element in the second run would fit
into the buffer. That becomes our <code>count1</code>. If we get an offset greater
than 0, we can bulk copy the previous elements from the buffer
(<code>[k, k + count1)</code>) to the range <code>[i, i + count1)</code> and increment both
<code>k</code> and <code>i</code> by <code>count1</code>. Once we're done, we know for sure we need to
copy the next element from the second run (<code>a[j]</code>), so we do that.</p>

<p>We then do the opposite: gallop left to find where the next element from
the buffer would fit into the second run. That becomes our <code>count2</code> and
if it is greater than 0, we bulk copy elements from the second run. Once
we're done, we again now that the next element to copy is at <code>t[k]</code>, so
we do that.</p>

<p>This loop repeats while either <code>count1</code> or <code>count2</code> is greater than
<code>MIN_GALLOP</code>. If galloping works, we also update <code>minGallop</code> to favor
future galloping. Each time we iterate, we decrement <code>minGallop</code>. Once
we're out of the loop, if it is due to both <code>count1</code> and <code>count2</code> being
smaller than <code>MIN_GALLOP</code>, we again adjust <code>minGallop</code> - first, if it
became negative, we make it 0. We then add 2 to penalize galloping
because our last iteration didn't meet <code>MIN_GALLOP</code>. As a reminder,
<code>minGallop</code> is used as the threshold in the first loop. These tweaks to
<code>minGallop</code> aim to optimize, depending on the data, when to enter gallop
mode and when to keep merging in normal mode.</p>

<p><code>minGallop</code> state should be maintained across multiple merges, and only
reset when we start a new sort - so we would make
<code>minGallop = MIN_GALLOP</code> in our main <code>sort</code> function, but otherwise rely
on the same value we are updating in <code>minGallop</code> for subsequent calls of
<code>mergeLo</code> and <code>mergeHi</code>. We made <code>minGallop</code> a global to keep the code
(relatively) simpler. To avoid globals, we should either put all
functions in a class and have minGallop be a member, or pass it through
as an argument through all functions that need it.</p>

<p>Finally, we copy the remaining elements in the buffer, if any:</p>
<div class="highlight"><pre><span/><span class="k">if</span> <span class="n">k</span> <span class="o">&lt;</span> <span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">:</span>
    <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">:</span><span class="n">hi</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">:</span><span class="n">mid</span> <span class="o">-</span> <span class="n">lo</span><span class="p">]</span>
</pre></div>

<p>We also have the mirrored <code>mergeHi</code> version:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">mergeHi</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">hi</span><span class="p">):</span>
    <span class="n">t</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">mid</span><span class="p">:</span><span class="n">hi</span><span class="p">]</span>
    <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">k</span> <span class="o">=</span> <span class="n">hi</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">hi</span> <span class="o">-</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span>
    <span class="k">global</span> <span class="n">minGallop</span>
    <span class="n">done</span> <span class="o">=</span> <span class="kc">False</span>

    <span class="k">while</span> <span class="ow">not</span> <span class="n">done</span><span class="p">:</span>
        <span class="n">count1</span><span class="p">,</span> <span class="n">count2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
        <span class="k">while</span> <span class="p">(</span><span class="n">count1</span> <span class="o">|</span> <span class="n">count2</span><span class="p">)</span> <span class="o">&lt;</span> <span class="n">minGallop</span><span class="p">:</span>
            <span class="k">if</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">&gt;</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
                <span class="n">count1</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="n">count2</span> <span class="o">=</span> <span class="mi">0</span>
                <span class="n">k</span> <span class="o">-=</span> <span class="mi">1</span>
            <span class="k">else</span><span class="p">:</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
                <span class="n">count1</span> <span class="o">=</span> <span class="mi">0</span>
                <span class="n">count2</span> <span class="o">+=</span> <span class="mi">1</span>
                <span class="n">j</span> <span class="o">-=</span> <span class="mi">1</span>
            <span class="n">i</span> <span class="o">-=</span> <span class="mi">1</span>

            <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">or</span> <span class="n">j</span> <span class="o">==</span> <span class="n">lo</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
                <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                <span class="k">break</span>

        <span class="k">if</span> <span class="n">done</span><span class="p">:</span>
            <span class="k">break</span>

        <span class="k">while</span> <span class="n">count1</span> <span class="o">&gt;=</span> <span class="n">MIN_GALLOP</span> <span class="ow">or</span> <span class="n">count2</span> <span class="o">&gt;=</span> <span class="n">MIN_GALLOP</span><span class="p">:</span>
            <span class="n">count1</span> <span class="o">=</span> <span class="n">j</span> <span class="o">-</span> <span class="n">lo</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">gallopRight</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">],</span> <span class="n">arr</span><span class="p">,</span> <span class="n">lo</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="n">lo</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="n">lo</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">count1</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="n">count1</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="n">count1</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
                <span class="n">i</span> <span class="o">-=</span> <span class="n">count1</span>
                <span class="n">j</span> <span class="o">-=</span> <span class="n">count1</span>
                <span class="k">if</span> <span class="n">j</span> <span class="o">==</span> <span class="n">lo</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
                    <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                    <span class="k">break</span>

            <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span><span class="p">]</span>
            <span class="n">i</span> <span class="o">-=</span> <span class="mi">1</span>
            <span class="n">k</span> <span class="o">-=</span> <span class="mi">1</span>

            <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
                <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                <span class="k">break</span>

            <span class="n">count2</span> <span class="o">=</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span> <span class="o">-</span> <span class="n">gallopLeft</span><span class="p">(</span><span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">t</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">k</span><span class="p">)</span>
            <span class="k">if</span> <span class="n">count2</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
                <span class="n">arr</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="n">count2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="n">k</span> <span class="o">-</span> <span class="n">count2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:</span><span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
                <span class="n">i</span> <span class="o">-=</span> <span class="n">count2</span>
                <span class="n">k</span> <span class="o">-=</span> <span class="n">count2</span>
                <span class="k">if</span> <span class="n">k</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
                    <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                    <span class="k">break</span>

            <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">arr</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
            <span class="n">i</span> <span class="o">-=</span> <span class="mi">1</span>
            <span class="n">j</span> <span class="o">-=</span> <span class="mi">1</span>
            <span class="k">if</span> <span class="n">j</span> <span class="o">==</span> <span class="n">lo</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
                <span class="n">done</span> <span class="o">=</span> <span class="kc">True</span>
                <span class="k">break</span>

            <span class="n">minGallop</span> <span class="o">-=</span> <span class="mi">1</span>

        <span class="k">if</span> <span class="n">minGallop</span> <span class="o">&lt;</span> <span class="mi">0</span><span class="p">:</span>
            <span class="n">minGallop</span> <span class="o">=</span> <span class="mi">0</span>
        <span class="n">minGallop</span> <span class="o">+=</span> <span class="mi">2</span>

    <span class="k">if</span> <span class="n">k</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
        <span class="n">arr</span><span class="p">[</span><span class="n">lo</span><span class="p">:</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="n">k</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
</pre></div>

<p>This is very similar to the previous one, so I won't break it into
pieces and explain, just note that since we are starting from the end of
the range and we go backwards, we use closed ranges: <code>i</code>, <code>j</code>, and <code>k</code>
always point to the last element of the range, not the one past the
last.</p>

<h2>Summary</h2>

<p>This is a very efficient sorting algorithm which relies on observed
properties of datasets in the real world. Quick recap:</p>

<ul>
<li>Depending on the size of the input, we determine a good size for
runs, so we can get balanced merges.</li>
<li>We traverse the array and identify runs. If the run is descending,
we reverse it. If we don't get enough elements in a run to
hopefully get balanced merges, we extend the run by adding more
elements and sorting them using binary sort.</li>
<li>We push runs on a stack which maintains a couple of invariants to,
again, keep merges balanced: the second to top run of the stack must
be longer than the top run and the third to top run must be longer
than the sum of the second and top runs.</li>
<li>If an invariant is violated, we start merging until we reestablish
it. We merge the second from the top run with the shortest of third
from top or top (again aiming for balanced overall merging). Merges
always merge consecutive runs.</li>
<li>Merge is optimized such that we first identify elements at the
beginning of the first run and the end of the second run which are
already in place, and we skip them.</li>
<li>Next, depending on which of the runs is larger, we merge either from
left or from right.</li>
<li>Merge happens in two modes: we compare and merge normally, until we
see one of the two runs we're merging consistently gets picked.
Once we pass a certain threshold, we switch to galloping mode.</li>
<li>Galloping aims to provide better performance than binary sort on
smaller datasets, where we expect to find the position we're
searching for earlier rather than later in the search. Galloping
tries to find a <code>k</code> such that the position we looking for is within
<code>A[(k - 1)^2]</code> and <code>A[k^2]</code>, then performs a binary search in the
interval.</li>
<li>Merging in galloping mode tries to find a range of elements in the
run that tends to win. This range can be bulk-copied in the merge
portion of the array more efficiently and skipping extra
comparisons.</li>
<li>If galloping becomes less effective, merge switches back to normal
mode.</li>
<li>Another heuristic keeps track of how well galloping mode performs
and either encourages or discourages entering galloping mode again.
This is persisted across multiple merges in a single sort.</li>
</ul>

<h2>Thoughts</h2>

<p>Is this sorting algorithm <em>beautiful</em>? Maybe not from a purely
syntactical/readability perspective. Compare it with the recursive
quicksort implementation in Haskell:</p>
<div class="highlight"><pre><span/><span class="nf">quicksort</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Ord</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="p">]</span><span class="w">  </span>
<span class="nf">quicksort</span><span class="w"> </span><span class="kt">[]</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">[]</span><span class="w">  </span>
<span class="nf">quicksort</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="kt">:</span><span class="n">xs</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w">   </span>
<span class="w">    </span><span class="kr">let</span><span class="w"> </span><span class="n">smallerSorted</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">quicksort</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">&lt;-</span><span class="w"> </span><span class="n">xs</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">x</span><span class="p">]</span><span class="w">  </span>
<span class="w">        </span><span class="n">biggerSorted</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="n">quicksort</span><span class="w"> </span><span class="p">[</span><span class="n">a</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">&lt;-</span><span class="w"> </span><span class="n">xs</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">x</span><span class="p">]</span><span class="w">  </span>
<span class="w">    </span><span class="kr">in</span><span class="w">  </span><span class="n">smallerSorted</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="p">[</span><span class="n">x</span><span class="p">]</span><span class="w"> </span><span class="o">++</span><span class="w"> </span><span class="n">biggerSorted</span>
</pre></div>

<p>Timsort is not a succinct algorithm. There are special cases,
optimizations for left to right and right to left cases, galloping,
which tries to beat binary search in some situations, multi-mode merges
and so on.</p>

<p>That said, everything in it has one purpose: sort real world data
efficiently. I find it beautiful for the amount of research that went
into it, the major insight that real world data is usually partially
sorted, and for how it adapts to various patterns in the data to improve
efficiency.</p>

<p>Most real world software looks more like Timsort than the Haskell
quicksort above. And while there is, unfortunately, way too much
accidental complexity in the world of software, there is a limit to how
much we can simplify before we can no longer model reality, or operate
efficiently. And, ultimately, that is what matters.</p>

<h2>References</h2>

<p>The final version of the code in this blog post is in <a href="https://gist.github.com/vladris/13bf84513e76b75a60b0eb761207541e">this GitHub
gist</a>
(be advised: implementation might be buggy).</p>

<p>Tim Peters has a very detailed explanation of the algorithm and all
optimizations in the Python codebase as
<a href="https://hg.python.org/cpython/file/tip/Objects/listsort.txt">listsort.txt</a>.
I do recommend reading this as it talks about all the research and
benchmarks that went into developing Timsort.</p>

<p>The C implementation of Timsort in the Python codebase is
<a href="https://hg.python.org/cpython/file/tip/Objects/listobject.c">listobject.c</a>.</p>

<p>The Python implementation relies on a lot of Python runtime constructs,
so it might be harder to read. My implementation is derived from the
OpenJDK implementation which I found very readable. That one is <a href="https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/TimSort.java">here on
GitHub</a>.</p>
]]></description>
      <pubDate>Thu, 30 Dec 2021 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/12/11/mental-poker.html</link>
      <guid>https://vladris.com/blog/2021/12/11/mental-poker.html</guid>
      <title><![CDATA[Mental Poker]]></title>
      <description><![CDATA[<h1>Mental Poker</h1>

<p>For the past year or so, I've been on the <a href="https://fluidframework.com/">Fluid
Framework</a> team. I won't go deeply into
the details of the framework, rather I'll quote a few paragraphs from
the <a href="https://fluidframework.com/docs/">Overview page</a>:</p>

<blockquote>
<p><strong>What is Fluid Framework?</strong></p>

<p>Fluid Framework is a collection of client libraries for distributing
and synchronizing shared state. These libraries allow multiple clients
to simultaneously create and operate on shared data structures using
coding patterns similar to those used to work with local data.</p>

<p><strong>Why Fluid?</strong></p>

<p>Because building low-latency, collaborative experiences is hard!</p>

<p>Fluid Framework offers:</p>

<ul>
<li>Client-centric application model with data persistence requiring
no custom server code.</li>
<li>Distributed data structures with familiar programming patterns.</li>
<li>Very low latency.</li>
</ul>

<p>Applications built with Fluid Framework require zero custom code on
the server to enable sophisticated data sync scenarios such as
real-time typing across text editors. Client developers can focus on
customer experiences while letting Fluid do the work of keeping data
in sync.</p>

<p><strong>How Fluid works</strong></p>

<p>Fluid was designed to deliver collaborative experiences with blazing
performance. To achieve this goal, the team kept the server logic as
simple and lightweight as possible. This approach helped ensure
virtually instant syncing across clients with very low server costs.</p>

<p>To keep the server simple, each Fluid client is responsible for its
own state. While previous systems keep a source of truth on the
server, the Fluid service is responsible for taking in data
operations, sequencing the operations, and returning the sequenced
operations to the clients. Each client is able to use that sequence to
independently and accurately produce the current state regardless of
the order it receives operations.</p>

<p>The following is a typical flow.</p>

<ul>
<li>Client code changes data locally.</li>
<li>Fluid runtime sends that change to the Fluid service.</li>
<li>Fluid service sequences that operation and broadcasts it to all
clients.</li>
<li>Fluid runtime incorporates that operation into local data and
raises a <code>valueChanged</code> event.</li>
<li>Client code handles that event (updates view, runs business
logic).</li>
</ul>
</blockquote>

<p>When using Fluid Framework, you model your data using a set of
<a href="https://fluidframework.com/docs/build/dds/">distributed data
structures</a> which can
internally merge changes from multiple clients.</p>

<p>During various hackathons, the team built various applications using
this data model. Of course, one of the first applications of any new
technology is games. This got me thinking about how we could model a
game on top of the framework.</p>

<p>There are some interesting constraints: games like chess or go don't
have any hidden information, but most games do require some hidden
information. Card games are especially interesting: each player holds
some cards that only themselves can see, some cards are face up on the
table (everyone can see them), while the rest of the deck is face down
on the table (nobody sees what order the cards are in).</p>

<p>With Fluid Framework, data is replicated across all clients. Assuming
we're playing a game of high stakes poker, we can't trust any other
client not to cheat. So a naÃ¯ve solution of sending the whole game state
(cards each player holds in their hand) to all clients and trust clients
not to peek won't work. We should assume that even if the game code
only shows a client their own cards, the client can cheat and use a
debugger to see what other players are holding in their hands.</p>

<p>We can trust the server, but there is very little the server can do for
us -while it can tell us which client changed state (distributed data
structure changes sequenced by the server include client ID), the server
itself cannot maintain private state. So, for example, we can't tell
the server to shuffle a deck of card without telling us what order the
cards end up in - all shared state is replicated across all clients.</p>

<p>In this zero-trust environment, where we assume other clients can cheat
and all shared state can be accessed by all clients, can we model a card
game? Surprisingly, the answer is <em>yes</em>.</p>

<h2>Mental Poker</h2>

<p>Turns out this exact problem has been studied for quite some time,
starting with the original 1981
<a href="https://people.csail.mit.edu/rivest/pubs/SRA81.pdf">paper</a> by Ron
Rivest, Adi Shamir, and Leonard Adleman (inventors of the RSA algorithm
among other things).</p>

<blockquote>
<p><em>Once there were two mental chess experts who had become tired of
their pastime. <q>Let's play mental poker, for variety</q> suggested
one. <q>Sure</q> said the other. <q>Just let me deal!</q></em></p>
</blockquote>

<p>Mental poker requires a commutative encryption function. If we encrypt
\(A\) using \(Key_1\) then encrypting the result using \(Key_2\), we should be
able to decrypt the result back to \(A\) regardless of the order of
decryption (first with \(Key_1\) and then with \(Key_2\), or vice-versa).</p>

<p>Here is how Alice and Bob play a game of mental poker:</p>

<ul>
<li>Alice takes a deck of cards (an array), shuffles the deck, generates
a secret key \(K_A\), and encrypts each card with \(K_A\).</li>
<li>Alice hands the shuffled and encrypted deck to Bob. At this point,
Bob doesn't know what order the cards are in (since Alice encrypted
the cards in the shuffled deck).</li>
<li>Bob takes the deck, shuffles it, generates a secret key \(K_B\), and
encrypts each card with \(K_B\).</li>
<li>Bob hands the deck to Alice. At this point, neither Alice nor Bob
know what order the cards are in. Alice got the deck back reshuffled
and re-encrypted by Bob, so she no longer knows where each card
ended up. Bob reshuffled an encrypted deck, so he also doesn't know
where each card is.</li>
</ul>

<p>At this point the cards are shuffled. In order to play, Alice and Bob
also need the capability to look at individual cards. In order to enable
this, the following steps must happen:</p>

<ul>
<li>Alice decrypts the shuffled deck with her secret key \(K_A\). At this
point she still doesn't know where each card is, as cards are still
encrypted with \(K_B\).</li>
<li>Alice generates a new set of secret keys, one for each card in the
deck. Assuming a 52-card deck, she generates
\(K_{A_1} ... K_{A_{52}}\) and encrypts each card in the deck with one
of the keys.</li>
<li>Alice hands the deck of cards to Bob. At this point, each card is
encrypted by Bob's key, \(B_K\), and one of Alice's keys, \(K_{A_i}\).</li>
<li>Bob decrypts the cards using his key \(K_B\). He still doesn't know
where each card is, as now the cards are encrypted with Alice's
keys.</li>
<li>Bob generates another set of secret keys, \(K_{B_1} ... K_{B_{52}}\),
and encrypts each card in the deck.</li>
<li>Now each card in the deck is encrypted with a unique key that only
Alice knows and a unique key only Bob knows.</li>
</ul>

<p>If Alice wants to look at a card, she asks Bob for his key for that
card. For example, if Alice draws the first card, encrypted with
\(K_{A_1}\) and \(K_{B_1}\), she asks Bob for \(K_{B_1}\). If Bob sends her
\(K_{B_1}\), she now has both keys to decrypt the card and <q>look</q> at it.
Bob still can't decrypt it because he doesn't have \(K_{A_1}\).</p>

<p>This way, as long as both Alice and Bob agree that one of them is
supposed to <q>see</q> a card, they exchange keys as needed to enable this.</p>

<p>At the end of the game, players reveal all keys to validate that no
cheating happened.</p>

<p>This approach can be extended to any number of players, each player
maintaining their own set of secret keys.</p>

<h2>Modeling a Game</h2>

<p>We can model a game using two data structures: one to keep track of the
cards, one to keep track of the <q>moves</q> in the game.</p>

<p>We can model a deck of cards using a distributed data structure that
holds the set of cards. Each client generates secret keys and initially
keeps them private (not part of the shared state). The deck of cards can
be shuffled and encrypted as described above, with each client updating
the shared set of cards.</p>

<p>We can model the gameplay using an append-only list of moves. For
example, if Alice <q>draws</q> the first card, the move can be modeled as
<code>DRAW 1</code>. If Bob agrees Alice should see the card, Bob can publish his
secret key \(K_{B_1}\) as <code>PUBLISH &lt;KB1&gt;</code>. Alice can now use her
\(K_{A_1}\) and the published \(K_{B_1}\) to decrypt the first card of the
deck (stored in the other data structure). <code>DRAW</code>, <code>PUBLISH</code>, and other
actions are part of the game semantics, which can be implemented and
interpreted by clients.</p>

<p>Note the deck of cards stays in place during the game. <q>Drawing</q> a
card means simply that all clients agree Alice should get the keys to
the card at index 1 and that the next card to be drawn is at index 2.
<q>Discarding</q> a card simply means Bob said he discards the card at
index 5. Depending on whether discarding is face up or face down, Bob
can publish \(K_{B_5}\) or keep it private until the end of the game. All
these actions are part of the game move list, and clients can construct
the game state based on these, without having to mutate the deck itself.</p>

<p>In terms of trust, we can say that, at any point, if a client can prove
the game is invalid (another client misbehaved), the game is cancelled.
If a player acts out of turn, or performs an action that they
shouldn't, the game is invalid. At the end of the game, the append-only
list should contain the full record of moves. With all keys available,
clients can replay and validate no cheating happened (for example Bob
claiming a card decrypted to an Ace, when in fact the card was a 2).
Clients can keep a local copy of the list of moves, and confirm no other
client rewrote history by tweaking the content of the list.</p>

<p>Establishing turn order can also be modeled through the append-only
action list: each player can start by adding a <code>SIT AT TABLE</code> action.
The framework will sequence these action in some order, which will
become the turn order. For example, if both Alice and Bob concurrently
<code>SIT AT TABLE</code>, the action list will contain both actions in some order.
Alice and Bob will take turns in that order.</p>

<p>Game semantics can be implemented as actions clients interpret. This is
outside the scope of this article.</p>

<h2>Resources</h2>

<p>As I mentioned, this problem has been studied for many decades. <a href="https://citeseerx.ist.psu.edu/viewdoc/download;jsessionid=589CF11E796235A23376DFE85C69B96E?doi=10.1.1.29.6679&amp;rep=rep1&amp;type=pdf">A
Toolbox for Mental Card
Games</a>
by Christian Schindelhauer describes many other techniques for playing
cards in a zero-trust environment.</p>

<p>There is also an open-source C++ library implementing the toolbox:
<a href="http://www.nongnu.org/libtmcg/">LibTMCG</a>.</p>

<p>The <a href="https://secret.cards">https://secret.cards</a> website seems to implement a card game using
mental poker techniques.</p>

<p>Wikipedia also has a good page on <a href="https://en.wikipedia.org/wiki/Mental_poker">mental
poker</a>.</p>
]]></description>
      <pubDate>Sat, 11 Dec 2021 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/11/27/notes-on-software-lifecycle.html</link>
      <guid>https://vladris.com/blog/2021/11/27/notes-on-software-lifecycle.html</guid>
      <title><![CDATA[Notes on Software Lifecycle]]></title>
      <description><![CDATA[<h1>Notes on Software Lifecycle</h1>

<p>I spent a lot of time lately looking at how our team can improve our
product's reliability and capability to respond to production
incidents. This got me thinking about the lifecycle of a contemporary
software project. The model I've been using for this looks like the
following:</p>

<p><img src="https://vladris.com/blog/2021/11/27/lifecycle.png" alt="image"/></p>

<p>At a high level, the cycle starts with <strong>engineers writing code</strong>. The
code gets merged and at some cadence, a new build is prepared for
release. This usually includes looking at a combination of testing and
telemetry signals for engineers to <strong>signoff on deploying the build</strong>.
In case tests fail or telemetry shows some anomalies, the deployment is
abandoned. If all looks good, the <strong>build gets deployed</strong>. Once the
build is exposed to a larger audience, more <strong>telemetry signals</strong> come
in.</p>

<p>Most software these days uses some form of controlled exposure. For
example, services might be deployed first in a dev environment, then in
a pre-production environment, then to production in one region, then to
all regions. Client software is similarly deployed to different rings,
for example new Office builds get deployed first to the Office
organization, then to all of Microsoft, then to customers who opted into
the Insider program, then to the whole world (I'm very much
oversimplifying things here, as release management for Office is way
more complex, but you get the idea). Telemetry signals from a ring feed
back into the <strong>build promotion</strong> process to give confidence that a
build can be exposed to a larger audience in the next ring.</p>

<p>Of course, sometimes things go wrong. We identify issues in the product,
either from <strong>telemetry signals</strong> or, worse, from <strong>user reports</strong>.
These become <strong>live site incidents</strong>. On-call engineers react to these
and try to <strong>mitigate</strong> as fast as possible. After the fire is put out,
a good practice is to run a <strong>postmortem</strong> to understand how the issue
happened and see how it can be prevented in the future. The learnings
usually translate into <strong>repair items</strong>, which get added to the
engineering backlog.</p>

<p>We can split this lifecycle into two parts: a <em>proactive</em> part and a
<em>reactive</em> part, which roughly map to the top and bottom halves of the
diagram.</p>

<h2>Proactive</h2>

<p>The proactive part deals with <em>what we can do to prevent issues from
making it to production</em>.</p>

<p><img src="https://vladris.com/blog/2021/11/27/proactive.png" alt="image"/></p>

<p>There are several things that could allow issues to slip through the
cracks.</p>

<h3>Code</h3>

<p>On the coding part, a feature might be missing tests to uncover
regressions, it might not be instrumented well enough to get good
signals, or it might not be put under a feature gate. Feature gates are
service-controlled flags that can be turned on/off to disable a feature.
These are extremely valuable for quickly mitigating production issues.</p>

<p>All of the above are addressed through education and engineering
culture: more junior engineers on the team might not even be aware of
all the requirements a feature should satisfy before it is <q>ready</q>
(see my <a href="https://vladris.com/blog/2021/08/12/shipping-a-feature.html">Shipping a
Feature</a>
post).</p>

<blockquote>
<p>A good practice is to have a <em>feature checklist</em>, a list of things
engineers need to consider before submitting a pull request. This
includes things like test coverage, telemetry, feature gates,
performance, accessibility (for UI) etc.</p>
</blockquote>

<p>Everyone writing code should know where this checklist is, and code
reviewers should keep it in mind while evaluating changes.</p>

<h3>Signoff for Build Promotion</h3>

<p>Two main issues would allow a regression to get passed the build
validation process: either there is a gap in validation, or missed
signals. This, of course, assumes that the code has tests and is
properly instrumented in the coding stage. Here, the person or persons
validating a build, either miss running some validation (automatic or
manual tests) or miss looking at a telemetry signal that would tell them
something is wrong.</p>

<p>Both of these issues can be addressed with automation.</p>

<blockquote>
<p>Have a <em>go/no-go dashboard</em> that aggregates all relevant signals (like
test run results, telemetry metrics).</p>
</blockquote>

<p>Of course, putting together such a dashboard and ensuring all code has
the right test automation and instrumentation is not easy.</p>

<h3>Telemetry Signals</h3>

<p>Telemetry could have gaps: issues could manifest themselves without us
receiving a signal. If this happens, we need to learn from these
incidents, understand where the gaps are, and eliminate them. More about
this on the <em>reactive</em> part.</p>

<h2>Reactive</h2>

<p>The reactive part deals with <em>how we can mitigate issues as quickly as
possible if they make it to production</em>.</p>

<p><img src="https://vladris.com/blog/2021/11/27/reactive.png" alt="image"/></p>

<h3>Incidents</h3>

<p>The entry point into the reactive cycle is an incident. An incident
alerts the on-call engineer and starts the mitigation process. The
sooner an incident is created, the sooner it can be addressed.</p>

<p>Issues here come from <em>alerting</em>. An alerting system runs automated
queries over incoming telemetry signals and looks for some anomalies or
thresholds. Things can go wrong in multiple ways:</p>

<ul>
<li><p>We can collect a lot of telemetry but not have the right queries to
notice sudden spikes, or drops, or other anomalies in the telemetry
stream.</p></li>
<li><p>We could be overly cautious and generate too many alerts, most of
them false positives, which makes it hard for on-call to figure out
when an alert is real.</p></li>
<li><p>Alerts might be very generic and not contain enough information for
on-call to easily mitigate.</p>

<blockquote>
<p>Alerts should be continuously finetuned to be accurate and
actionable, with as few false positives as possible.</p>
</blockquote></li>
</ul>

<p>Telemetry signals, even if correct, can be impacted by multiple things
outside of our control. For example, usage might raise or drop sharply
during weekends (depending on whether we're talking about a game or a
productivity app) or holidays. This makes it even harder to develop
accurate alerts.</p>

<p>The worst case is when issues get reported by customers before we see
any alerts: this signifies a big gap and a postmortem should identify
the follow up work (see <em>postmortems</em> below).</p>

<h3>Mitigation</h3>

<p>Several things can make mitigation harder. The on-call engineer might
not know how to handle certain types of incidents.</p>

<blockquote>
<p>It's a good idea to have a <em>troubleshooting guide</em> (TSG) for each
type of alert, where an area expert details the steps to mitigate an
issue.</p>
</blockquote>

<p>Another common issue is there is no easy mitigation. This goes back to
our <strong>coding</strong> section: code should be behind feature gates, so
mitigation is as easy as flipping a switch.</p>

<p>Yet another common issue, which we covered in the previous section when
we discussed alerts, is not having enough information to easily pinpoint
the actual issue. The on-call engineer sees an incidents, knows
something is wrong, but not enough information is available for a quick
mitigation. Alerts should contain enough information to be useful.</p>

<h3>Postmortems</h3>

<p>Postmortems are an invaluable tool for learning from incidents.
Postmortems are reviews of incidents once mitigated, root caused, and
understood, where the team gets together to discuss what happened and
take steps to prevent the same type of issue form happening in the
future. A postmortem is not about blaming, it is about answering the
following question:</p>

<blockquote>
<p>What can we do to ensure this doesn't happen in the future?</p>
</blockquote>

<p>A postmortem that doesn't answer this question is not that useful. A
good postmortem identifies one or more work items that can be handed to
engineering to implement additional guardrails so the same issue
doesn't recur.</p>

<h3>Repair Items</h3>

<p>Finally, identifying repair items is not enough. A long backlog of
repair items that nobody gets around to implement won't make things any
easier.</p>

<blockquote>
<p>Engineers should treat repair items with priority.</p>
</blockquote>

<p>Repair items are some of the most critical work items: we've seen
incidents in production, we know the scope of the impact, and we know
the work needed to prevent them in the future.</p>

<h2>Summary</h2>

<p>In this post we looked at a model of software lifecycle, consisting of a
<em>proactive</em> part: engineers writing code, a signoff process to promote a
build, and signals to increase the audience for a build; and a <em>reactive
part</em>: a live site incident, which on-call engineers mitigate, the team
postmortems, and comes up with a set of repair items.</p>

<p>We also looked at some of the common issues across these various parts
of the lifecycle, and some best practices.</p>

<p>This was a very high-level overview - each of these steps has a lot of
depth, from writing safe code, to release management, to telemetry
models, site reliability engineering, and so on. All of these are
critical parts of shipping software.</p>
]]></description>
      <pubDate>Sat, 27 Nov 2021 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/09/24/machine-learning-on-azure-part-3.html</link>
      <guid>https://vladris.com/blog/2021/09/24/machine-learning-on-azure-part-3.html</guid>
      <title><![CDATA[Machine Learning on Azure - Part 3]]></title>
      <description><![CDATA[<h1>Machine Learning on Azure - Part 3</h1>

<p>This is an excerpt from chapter 7 of my book, <a href="https://www.manning.com/books/azure-data-engineering">Data Engineering on
Azure</a>, which
deals with machine learning workloads. This is part 3 in a 3 part
series. In this post, we'll run the model we created in <a href="https://vladris.com/blog/2021/09/10/machine-learning-on-azure-part-1.html">part
1</a>
on the Azure Machine Learning (AML) infrastructure we set up in <a href="https://vladris.com/blog/2021/09/17/machine-learning-on-azure-part-2.html">part
2</a>
.</p>

<h2>Running ML in the cloud</h2>

<p>We use the Python Azure Machine Learning SDK for this, so the first step
is to install it using the Python package manager (pip). First, make
sure pip is up-to-date. (If there is a newer pip version, you should see
a message printed to the console suggesting you upgrade when you run a
pip command.) You can update pip by running
<code>python -m pip install --upgrade pip</code> as an administrator. Once pip is
up-to-date, install the Azure Machine Learning SDK with the command in
the following listing:</p>
<div class="highlight"><pre><span/><span class="n">pip</span> <span class="n">install</span> <span class="n">azureml-sdk</span>
</pre></div>

<p>Let's now write a Python script to publish our original ML model to the
cloud, with all the required configuration. We'll call this
<code>pipeline.py</code>.</p>
<div class="highlight"><pre><span/><span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core</span><span class="w"> </span><span class="kn">import</span> <span class="n">Workspace</span><span class="p">,</span> <span class="n">Datastore</span><span class="p">,</span> <span class="n">Dataset</span><span class="p">,</span> <span class="n">Model</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.authentication</span><span class="w"> </span><span class="kn">import</span> <span class="n">ServicePrincipalAuthentication</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.compute</span><span class="w"> </span><span class="kn">import</span> <span class="n">AmlCompute</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.conda_dependencies</span><span class="w"> </span><span class="kn">import</span> <span class="n">CondaDependencies</span> 
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.runconfig</span><span class="w"> </span><span class="kn">import</span> <span class="n">RunConfiguration</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.pipeline.core</span><span class="w"> </span><span class="kn">import</span> <span class="n">Pipeline</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.pipeline.steps.python_script_step</span><span class="w"> </span><span class="kn">import</span> <span class="n">PythonScriptStep</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">os</span>  

<span class="n">tenant_id</span> <span class="o">=</span> <span class="s1">'&lt;your tenant ID&gt;'</span>
<span class="n">subscription_id</span> <span class="o">=</span> <span class="s1">'&lt;your Azure subscription GUID&gt;'</span>
<span class="n">service_principal_id</span> <span class="o">=</span> <span class="s1">'&lt;your service principal ID&gt;'</span>
<span class="n">resource_group</span>  <span class="o">=</span> <span class="s1">'aml-rg'</span>
<span class="n">workspace_name</span>  <span class="o">=</span> <span class="s1">'aml'</span>

<span class="c1">## Auth </span>
<span class="n">auth</span> <span class="o">=</span> <span class="n">ServicePrincipalAuthentication</span><span class="p">(</span>
    <span class="n">tenant_id</span><span class="p">,</span> 
    <span class="n">service_principal_id</span><span class="p">,</span> 
    <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'SP_PASSWORD'</span><span class="p">))</span>  

<span class="c1">## Workspace </span>
<span class="n">workspace</span> <span class="o">=</span> <span class="n">Workspace</span><span class="p">(</span> 
    <span class="n">subscription_id</span> <span class="o">=</span> <span class="n">subscription_id</span><span class="p">,</span>
    <span class="n">resource_group</span> <span class="o">=</span> <span class="n">resource_group</span><span class="p">,</span>
    <span class="n">workspace_name</span> <span class="o">=</span> <span class="n">workspace_name</span><span class="p">,</span>
    <span class="n">auth</span><span class="o">=</span><span class="n">auth</span><span class="p">)</span>

<span class="c1">## Datastore </span>
<span class="n">datastore</span> <span class="o">=</span> <span class="n">Datastore</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">workspace</span><span class="p">,</span> <span class="s1">'MLData'</span><span class="p">)</span>

<span class="c1">## Compute target </span>
<span class="n">compute_target</span> <span class="o">=</span> <span class="n">AmlCompute</span><span class="p">(</span><span class="n">workspace</span><span class="p">,</span> <span class="s1">'d1compute'</span><span class="p">)</span>

<span class="c1">## Input </span>
<span class="n">model_input</span> <span class="o">=</span> <span class="n">Dataset</span><span class="o">.</span><span class="n">File</span><span class="o">.</span><span class="n">from_files</span><span class="p">(</span> 
    <span class="p">[(</span><span class="n">datastore</span><span class="p">,</span> <span class="s1">'/models/highspenders/input.csv'</span><span class="p">)])</span><span class="o">.</span><span class="n">as_mount</span><span class="p">()</span>

<span class="c1">## Python package configuration  </span>
<span class="n">conda_deps</span> <span class="o">=</span> <span class="n">CondaDependencies</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
    <span class="n">pip_packages</span><span class="o">=</span><span class="p">[</span><span class="s1">'pandas'</span><span class="p">,</span> <span class="s1">'sklearn'</span><span class="p">,</span> <span class="s1">'azureml-core'</span><span class="p">,</span> <span class="s1">'azureml-dataprep'</span><span class="p">])</span>

<span class="n">run_config</span> <span class="o">=</span> <span class="n">RunConfiguration</span><span class="p">(</span><span class="n">conda_dependencies</span><span class="o">=</span><span class="n">conda_deps</span><span class="p">)</span>

<span class="c1">## Train step </span>
<span class="n">trainStep</span> <span class="o">=</span> <span class="n">PythonScriptStep</span><span class="p">(</span> 
    <span class="n">script_name</span><span class="o">=</span><span class="s1">'highspenders.py'</span><span class="p">,</span>
    <span class="n">arguments</span><span class="o">=</span><span class="p">[</span><span class="s1">'--input'</span><span class="p">,</span> <span class="n">model_input</span><span class="p">],</span>
    <span class="n">inputs</span><span class="o">=</span><span class="p">[</span><span class="n">model_input</span><span class="p">],</span>
    <span class="n">runconfig</span><span class="o">=</span><span class="n">run_config</span><span class="p">,</span>
    <span class="n">compute_target</span><span class="o">=</span><span class="n">compute_target</span><span class="p">)</span>  

<span class="c1">## Submit pipeline </span>
<span class="n">pipeline</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="p">(</span><span class="n">workspace</span><span class="o">=</span><span class="n">workspace</span><span class="p">,</span> <span class="n">steps</span><span class="o">=</span><span class="p">[</span><span class="n">trainStep</span><span class="p">])</span>

<span class="n">published_pipeline</span> <span class="o">=</span> <span class="n">pipeline</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span>
    <span class="n">name</span><span class="o">=</span><span class="s1">'HighSpenders'</span><span class="p">,</span>
    <span class="n">description</span><span class="o">=</span><span class="s1">'High spenders model'</span><span class="p">,</span>
    <span class="n">continue_on_step_failure</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>

<span class="nb">open</span><span class="p">(</span><span class="s1">'highspenders.id'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">published_pipeline</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
</pre></div>

<p>We'll break down this script and discuss each part. First, we have the
required imports and the additional parameters we need.</p>
<div class="highlight"><pre><span/><span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core</span><span class="w"> </span><span class="kn">import</span> <span class="n">Workspace</span><span class="p">,</span> <span class="n">Datastore</span><span class="p">,</span> <span class="n">Dataset</span><span class="p">,</span> <span class="n">Model</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.authentication</span><span class="w"> </span><span class="kn">import</span> <span class="n">ServicePrincipalAuthentication</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.compute</span><span class="w"> </span><span class="kn">import</span> <span class="n">AmlCompute</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.conda_dependencies</span><span class="w"> </span><span class="kn">import</span> <span class="n">CondaDependencies</span> 
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.runconfig</span><span class="w"> </span><span class="kn">import</span> <span class="n">RunConfiguration</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.pipeline.core</span><span class="w"> </span><span class="kn">import</span> <span class="n">Pipeline</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.pipeline.steps.python_script_step</span><span class="w"> </span><span class="kn">import</span> <span class="n">PythonScriptStep</span>
<span class="kn">import</span><span class="w"> </span><span class="nn">os</span>  

<span class="n">tenant_id</span> <span class="o">=</span> <span class="s1">'&lt;your tenant ID&gt;'</span>
<span class="n">subscription_id</span> <span class="o">=</span> <span class="s1">'&lt;your Azure subscription GUID&gt;'</span>
<span class="n">service_principal_id</span> <span class="o">=</span> <span class="s1">'&lt;your service principal ID&gt;'</span>
<span class="n">resource_group</span>  <span class="o">=</span> <span class="s1">'aml-rg'</span>
<span class="n">workspace_name</span>  <span class="o">=</span> <span class="s1">'aml'</span>
</pre></div>

<p>We import a set of packages from the <code>azureml-sdk</code>. We need the tenant
ID, subscription ID, and service principal ID we will use to connect to
the Azure Machine Learning service. We created the service principal in
<a href="https://vladris.com/blog/2021/09/17/machine-learning-on-azure-part-2.html">part
2</a>.
We stored it in the <code>$sp</code> variable. In case you closed that PowerShell
session and no longer have the <code>$sp</code> variable, you can simply rerun the
scripts we covered in part 2 to create a new service principal and grant
it the required permissions.</p>

<p>You can get the service principal ID from <code>$sp.appId</code> in PowerShell.
Similarly, you can get the tenant ID from <code>$sp.tenant</code>. The subscription
ID is the GUID of your Azure subscription.</p>

<p>Use these to intialize the <code>tenant_id</code>, <code>subscription_id</code>, and
<code>service_principal_id</code> in the script above.</p>

<p>Next, we connect to the workspace using the service principal and get
the data store (<code>MLData</code>) and compute target (<code>d1compute</code>) needed by our
model. The following listing shows the steps.</p>
<div class="highlight"><pre><span/><span class="c1">## Auth </span>
<span class="n">auth</span> <span class="o">=</span> <span class="n">ServicePrincipalAuthentication</span><span class="p">(</span>
    <span class="n">tenant_id</span><span class="p">,</span> 
    <span class="n">service_principal_id</span><span class="p">,</span> 
    <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'SP_PASSWORD'</span><span class="p">))</span>  

<span class="c1">## Workspace </span>
<span class="n">workspace</span> <span class="o">=</span> <span class="n">Workspace</span><span class="p">(</span> 
    <span class="n">subscription_id</span> <span class="o">=</span> <span class="n">subscription_id</span><span class="p">,</span>
    <span class="n">resource_group</span> <span class="o">=</span> <span class="n">resource_group</span><span class="p">,</span>
    <span class="n">workspace_name</span> <span class="o">=</span> <span class="n">workspace_name</span><span class="p">,</span>
    <span class="n">auth</span><span class="o">=</span><span class="n">auth</span><span class="p">)</span>

<span class="c1">## Datastore </span>
<span class="n">datastore</span> <span class="o">=</span> <span class="n">Datastore</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">workspace</span><span class="p">,</span> <span class="s1">'MLData'</span><span class="p">)</span>

<span class="c1">## Compute target </span>
<span class="n">compute_target</span> <span class="o">=</span> <span class="n">AmlCompute</span><span class="p">(</span><span class="n">workspace</span><span class="p">,</span> <span class="s1">'d1compute'</span><span class="p">)</span>
</pre></div>

<p>Here we define a service principal authentication as <code>Auth</code> and use the
environment variable <code>SP_PASSWORD</code> to retrieve the service principal
secret. We set this variable in part 2, after we created the principal.</p>

<p>We connect to the Azure Machine Learning workspace with the given
subscription ID, resource group, name, and auth. We then retrieve the
datastore (<code>MLData</code>) and compute target (<code>d1compute</code>) from the
workspace.</p>

<p>We need these to set up our deployment: the data store is where we have
our input, while the compute target is where the model trains. The
following listing shows how we can specify the model input.</p>
<div class="highlight"><pre><span/><span class="c1">## Input </span>
<span class="n">model_input</span> <span class="o">=</span> <span class="n">Dataset</span><span class="o">.</span><span class="n">File</span><span class="o">.</span><span class="n">from_files</span><span class="p">(</span> 
    <span class="p">[(</span><span class="n">datastore</span><span class="p">,</span> <span class="s1">'/models/highspenders/input.csv'</span><span class="p">)])</span><span class="o">.</span><span class="n">as_mount</span><span class="p">()</span>
</pre></div>

<p>The <code>from_files()</code> method takes a list of files. Each element of the
list is a tuple consisting of a data store and a path. The <code>as_mount()</code>
method ensures the file is mounted and made available to the compute
that trains the model.</p>

<blockquote>
<p>Azure Machine Learning <em>datasets</em> reference a data source location,
along with a copy of its metadata. This allows models to seamlessly
access data during training.</p>
</blockquote>

<p>Next, we'll specify the Python packages required by our model, from
which we can initialize a run configuration. If you remember from part
1, we used <code>pandas</code> and <code>sklearn</code>. We'll also need the <code>azureml-core</code>
and <code>azureml-dataprep</code> packages required by the runtime. The next
listing shows how to create the run configuration.</p>
<div class="highlight"><pre><span/><span class="c1">## Python package configuration  </span>
<span class="n">conda_deps</span> <span class="o">=</span> <span class="n">CondaDependencies</span><span class="o">.</span><span class="n">create</span><span class="p">(</span>
    <span class="n">pip_packages</span><span class="o">=</span><span class="p">[</span><span class="s1">'pandas'</span><span class="p">,</span> <span class="s1">'sklearn'</span><span class="p">,</span> <span class="s1">'azureml-core'</span><span class="p">,</span> <span class="s1">'azureml-dataprep'</span><span class="p">])</span>

<span class="n">run_config</span> <span class="o">=</span> <span class="n">RunConfiguration</span><span class="p">(</span><span class="n">conda_dependencies</span><span class="o">=</span><span class="n">conda_deps</span><span class="p">)</span>
</pre></div>

<p><em>Conda</em> stands for Anaconda, a Python and R open source distribution of
common data science packages. Anaconda simplifies package management and
dependencies and is commonly used in data science projects because it
provides a stable environment for this type of workload. Azure Machine
Learning also uses it under the hood.</p>

<p>Next, let's create a step for training our model. In our case, this is
a <code>PythonScriptStep</code>, a step that executes Python code. We'll provide
the name of the script (from our previous section), the command-line
arguments, the inputs, run configuration, and compute target. The
following listing shows the details.</p>
<div class="highlight"><pre><span/><span class="c1">## Train step </span>
<span class="n">trainStep</span> <span class="o">=</span> <span class="n">PythonScriptStep</span><span class="p">(</span> 
    <span class="n">script_name</span><span class="o">=</span><span class="s1">'highspenders.py'</span><span class="p">,</span>
    <span class="n">arguments</span><span class="o">=</span><span class="p">[</span><span class="s1">'--input'</span><span class="p">,</span> <span class="n">model_input</span><span class="p">],</span>
    <span class="n">inputs</span><span class="o">=</span><span class="p">[</span><span class="n">model_input</span><span class="p">],</span>
    <span class="n">runconfig</span><span class="o">=</span><span class="n">run_config</span><span class="p">,</span>
    <span class="n">compute_target</span><span class="o">=</span><span class="n">compute_target</span><span class="p">)</span>
</pre></div>

<p>We specify the script to upload/run with <code>script_name</code>. This is our
<code>highspenders.py</code> model we created in part 1. We set the arguments we
want passed to the script as <code>arguments</code>. Here, <code>model_input</code> resolves
at runtime to the path where the data is mounted on the node running the
script. We set the inputs, run configuration, and compute target to run
on as <code>inputs</code>, <code>runconfig</code>, and <code>compute_target</code>.</p>

<p>We can chain multiple steps together, but we only need one in our case.
One or more steps form a ML <em>pipeline</em>.</p>

<blockquote>
<p>An Azure Machine Learning <em>pipeline</em> simplifies building ML workflows
including data preparation, training, validation, scoring, and
deployment.</p>
</blockquote>

<p>Pipelines are an important concept in Azure Machine Learning. These
capture all the information needed to run a ML workflow. The following
listing shows how we can create and submit a pipeline to our workspace.</p>
<div class="highlight"><pre><span/><span class="c1">## Submit pipeline </span>
<span class="n">pipeline</span> <span class="o">=</span> <span class="n">Pipeline</span><span class="p">(</span><span class="n">workspace</span><span class="o">=</span><span class="n">workspace</span><span class="p">,</span> <span class="n">steps</span><span class="o">=</span><span class="p">[</span><span class="n">trainStep</span><span class="p">])</span>

<span class="n">published_pipeline</span> <span class="o">=</span> <span class="n">pipeline</span><span class="o">.</span><span class="n">publish</span><span class="p">(</span>
    <span class="n">name</span><span class="o">=</span><span class="s1">'HighSpenders'</span><span class="p">,</span>
    <span class="n">description</span><span class="o">=</span><span class="s1">'High spenders model'</span><span class="p">,</span>
    <span class="n">continue_on_step_failure</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>

<span class="nb">open</span><span class="p">(</span><span class="s1">'highspenders.id'</span><span class="p">,</span> <span class="s1">'w'</span><span class="p">)</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">published_pipeline</span><span class="o">.</span><span class="n">id</span><span class="p">)</span>
</pre></div>

<p>We create a pipeline with a single step, <code>trainStep</code> in our workspace.
We publish the pipeline. We'll save the GUID of the published pipeline
into the <code>highspenders.id</code> file so we can refer to it later.</p>

<p>This covers the whole <code>pipeline.py</code> script. Our pipeline automation is
almost complete. But before calling this script to create the pipeline,
let's make one small addition to our high spender model. While we could
do all of the previous steps without touching our original model code,
we add the final step to the model code itself. Remember that once the
model is trained, we save it to disk as <code>outputs/highspender.pkl</code>.</p>

<p>For this step, we'll make one Azure Machine Learning-specific addition:
taking the trained model and storing it in the workspace. Add the lines
in the following listing to the <code>highspenders.py</code> model we created in
part 1 (not to <code>pipeline.py</code>, which we just covered).</p>
<div class="highlight"><pre><span/><span class="c1">## Register model </span>
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core</span><span class="w"> </span><span class="kn">import</span> <span class="n">Model</span> 
<span class="kn">from</span><span class="w"> </span><span class="nn">azureml.core.run</span><span class="w"> </span><span class="kn">import</span> <span class="n">Run</span>  

<span class="n">run</span> <span class="o">=</span> <span class="n">Run</span><span class="o">.</span><span class="n">get_context</span><span class="p">()</span>
<span class="n">workspace</span> <span class="o">=</span> <span class="n">run</span><span class="o">.</span><span class="n">experiment</span><span class="o">.</span><span class="n">workspace</span>
<span class="n">model</span> <span class="o">=</span> <span class="n">Model</span><span class="o">.</span><span class="n">register</span><span class="p">(</span>
    <span class="n">workspace</span><span class="o">=</span><span class="n">workspace</span><span class="p">,</span>
    <span class="n">model_name</span><span class="o">=</span><span class="s1">'highspender'</span><span class="p">,</span>
    <span class="n">model_path</span><span class="o">=</span><span class="n">model_path</span><span class="p">)</span>
</pre></div>

<p>Note the call to <code>Run.get_context()</code> and how we use this to retrieve the
workspace. In <code>pipeline.py</code>, we provided the subscription ID, resource
group, and workspace name. That is how we can get a workspace from
outside Azure Machine Learning. In this case, though, the code runs in
Azure Machine Learning as part of our pipeline. This gives us additional
context that we can use to retrieve the workspace at runtime. Every run
of a pipeline in Azure Machine Learning is called an <em>experiment</em>.</p>

<blockquote>
<p>Azure Machine Learning <em>experiments</em> represent one execution of a
pipeline. When we rerun a pipeline, we have a new experiment.</p>
</blockquote>

<p>We are all set! Let's run the <code>pipeline.py</code> script to publish our
pipeline to the workspace. The following listing provides the command
for this step.</p>
<div class="highlight"><pre><span/><span class="n">python</span> <span class="n">pipeline</span><span class="p">.</span><span class="n">py</span>
</pre></div>

<p>The GUID matters! If we rerun the script, it registers another pipeline
with the same name but a different GUID. Azure Machine Learning does not
update pipelines in place. We have the option to disable pipelines so
these don't clutter the workspace, but not to update those. Let's kick
off the pipeline using Azure CLI as the next listing shows.</p>
<div class="highlight"><pre><span/><span class="nv">$pipelineId</span> <span class="p">=</span> <span class="nb">Get-Content</span> <span class="n">-Path</span> <span class="n">highspenders</span><span class="p">.</span><span class="n">id</span>

<span class="n">az</span> <span class="n">ml</span> <span class="n">run</span> <span class="nb">submit-pipeline</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-pipeline-id</span> <span class="nv">$pipelineId</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-workspace-name</span> <span class="n">aml</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-resource-group</span> <span class="n">aml-rg</span>
</pre></div>

<p>We read the pipeline ID from the <code>highspenders.id</code> file produced in the
previous step into the <code>$pipelineId</code> variable. We then submit a new run.</p>

<p>Check the UI at <a href="https://ml.azure.com">https://ml.azure.com</a>. You should see the pipeline
under the Pipelines section, the run we just kicked off under the
Experiments section. Once the model is trained, you'll see the model
output under the Models section.</p>

<h2>Azure Machine Learning recap</h2>

<p>After implementing a model in Python, we started with provisioning a
workspace, which is the top-level container for all Azure Machine
Learning-related artifacts. Next, we created a compute target, which
specifies the type of compute our model runs on. We can define as many
compute targets as needed; some models require more resources than
others, some require GPUs, etc. Azure provides many types of VM images
suited to all these workloads. A main advantage of using compute targets
in Azure Machine Learning is that compute is provisioned on demand when
we run a pipeline. Once the pipeline finishes, compute gets
deprovisioned. This allows us to scale elastically and only pay for what
we need.</p>

<p>We then attached a data store. Data stores are an abstraction over
existing storage services, and these allow Azure Machine Learning
connections to read the data. The main advantage of using data stores is
that these abstract away access control, so our data scientists don't
need to worry about authenticating against the storage service.</p>

<p>With the infrastructure in place, we proceeded to set up a pipeline for
our model. A pipeline specifies all the requirements and steps our
execution needs to take. There are many pipelines in Azure: Azure DevOps
Pipelines are focused on DevOps, provisioning resources, and in general,
providing automation around Git; Azure Data Factory pipelines are
focused on ETL, data movement, and orchestration; Azure Machine Learning
Pipelines are meant for ML workflows, where we set up the environment
and then execute a set of steps to train, validate, and publish a model.</p>

<p>Our pipeline included a dataset (our input), a compute target, a set of
Python package dependencies, a run configuration, and a step to run a
Python script. We also enhanced our original model code to publish the
model in AML. This takes the result of our training run and makes it
available in the workspace. Then we published the pipeline to our Azure
Machine Learning workspace and submitted a run, which in Azure Machine
Learning is called an experiment.</p>

<h2>Next steps</h2>

<p>We will stop here with the series of article. Grab the book to see how
we can apply DevOps to our ML scenario. In the book, we go over putting
both the model code and <code>pipeline.py</code> in Git, then deploy updates using
Azure DevOps Pipelines. We also cover orchestrating ML runs with Azure
Data Factory, which includes getting the input data ready, running an
Azure Machine Learning experiment, and handling the output.</p>

<p><img src="https://vladris.com/blog/2021/09/24/mlops.png" alt="image"/></p>

<p>All of this and more in <a href="https://www.manning.com/books/azure-data-engineering">Data Engineering on
Azure</a>.</p>
]]></description>
      <pubDate>Fri, 24 Sep 2021 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/09/17/machine-learning-on-azure-part-2.html</link>
      <guid>https://vladris.com/blog/2021/09/17/machine-learning-on-azure-part-2.html</guid>
      <title><![CDATA[Machine Learning on Azure - Part 2]]></title>
      <description><![CDATA[<h1>Machine Learning on Azure - Part 2</h1>

<p>This is an excerpt from chapter 7 of my book, <a href="https://www.manning.com/books/azure-data-engineering">Data Engineering on
Azure</a>, which
deals with machine learning workloads. This is part 2 in a 3 part
series. In this post, we'll explore the Azure Machine Learning (AML)
service and set it up in preparation of running our model in the cloud.</p>

<p>In this post, like throughout the book, we'll be using PowerShell Core
and Azure CLI to interact with Azure. You can install PowerShell Core
from <a href="https://github.com/PowerShell/Powershell">here</a>. Then from the
PowerShell Core shell, you can install Azure CLI using the following
command:</p>
<div class="highlight"><pre><span/><span class="nb">Invoke-WebRequest</span> <span class="n">-Uri</span> <span class="n">https</span><span class="p">://</span><span class="n">aka</span><span class="p">.</span><span class="n">ms</span><span class="p">/</span><span class="n">installazurecliwindows</span> <span class="p">`</span>
<span class="n">-OutFile</span> <span class="p">.\</span><span class="n">AzureCLI</span><span class="p">.</span><span class="n">msi</span><span class="p">;</span> <span class="nb">Start-Process</span> <span class="n">msiexec</span><span class="p">.</span><span class="n">exe</span> <span class="p">`</span>
<span class="n">-Wait</span> <span class="n">-ArgumentList</span>  <span class="s1">'/I AzureCLI.msi /quiet'</span><span class="p">;</span> <span class="nb">rm </span><span class="p">.\</span><span class="n">AzureCLI</span><span class="p">.</span><span class="n">msi</span>
</pre></div>

<p>Once Azure CLI is installed, you can use <code>az</code> commands as we'll see
throughout this post. First, log into your Azure account:</p>
<div class="highlight"><pre><span/><span class="n">az</span> <span class="n">login</span>
</pre></div>

<h2>Introducing Azure Machine Learning</h2>

<p>Azure Machine Learning is Microsoft's Azure offering for creating and
managing ML solutions in the cloud. An instance of Azure Machine
Learning is called a workspace.</p>

<blockquote>
<p>A <em>workspace</em> is the top-level resource for Azure Machine Larning,
providing a centralized place to work with all the artifacts you
create.</p>
</blockquote>

<p>In this post, we'll create and configure a workspace, then we'll look
at everything needed for taking our high spender model we developed in
<a href="https://vladris.com/blog/2021/09/10/machine-learning-on-azure-part-1.html">part
1</a>
from our local machine and running it on Azure.</p>

<h2>Creating a workspace</h2>

<p>We'll start by using Azure CLI to create a workspace. First, we install
the <code>azure-cli-ml</code> extension, then we create a new resource group called
<code>aml-rg</code> to host our ML workloads, and finally, we create a workspace in
the new resource group. The following listing shows the steps:</p>
<div class="highlight"><pre><span/><span class="n">az</span> <span class="n">extension</span> <span class="n">add</span> <span class="n">-n</span> <span class="n">azure-cli-ml</span>

<span class="n">az</span> <span class="nb">group </span><span class="n">create</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-location</span> <span class="s2">"Central US"</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-name</span> <span class="n">aml-rg</span>  

<span class="n">az</span> <span class="n">ml</span> <span class="n">workspace</span> <span class="n">create</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-workspace-name</span> <span class="n">aml</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-location</span> <span class="s2">"Central US"</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-resource-group</span> <span class="n">aml-rg</span>
</pre></div>

<p>The first line adds the <code>azure-cli-ml</code> extension. The second line
creates the <code>aml-rg</code> resource group in the Central US Azure region. The
last command creates a new Azure Machine Learning workspace named <code>aml</code>
in the resource group.</p>

<p>The same way Azure Data Explorer (ADX) has a web UI accessible at
<a href="https://dataexplorer.azure.com/">https://dataexplorer.azure.com/</a> and Azure Data Factory has a web UI
accessible at <a href="https://adf.azure.com/">https://adf.azure.com/</a>, Azure Machine Learning also has
a web UI that you can find at <a href="https://ml.azure.com/">https://ml.azure.com/</a>. We will stick to
the Azure CLI and the Python SDK to provision resources, but I encourage
you to try the web UI. As we create more artifacts in this section, you
can use the web UI to see how these are represented there. If you visit
the web UI, you will see a navigation bar on the right with three
sections: Author, Assets, and Manage. The following figure shows the
navigation bar.</p>

<p><img src="https://vladris.com/blog/2021/09/17/navbar.png" alt="image"/></p>

<p>The Author section contains Notebooks, Automated ML, and Designer. We
won't focus on these but here is a quick walkthrough: Notebooks enables
users to store Jupyter notebooks and other files directly in the
workspace; Automated ML is a codeless solution for implementing ML; and
the Designer is a visual drag-and-drop editor for ML. We won't focus on
these features because these facilitate model development. We'll look
at the DevOps aspects of ML using our existing Python model as an
example, so this is less relevant for us. Of course, we could've built
our model in Azure Machine Learning directly, but this way, we learn how
we can onboard a model that wasn't created specifically to run on Azure
Machine Learning.</p>

<p>We will, however, touch on most of the items in the Assets and Manage
sections. Assets are some of the concepts Azure Machine Learning deals
with, such as Experiments and Models. We'll cover these soon. The
Manage section deals with the compute and storage resources for AML.
Let's zoom in on these.</p>

<h2>Creating an Azure Machine Learning compute target</h2>

<p>One of the great features of Azure Machine Learning is that it can
automatically scale compute resources to train models. Remember, compute
in the cloud refers to CPU and RAM resources. A virtual machine (VM) in
the cloud provides CPU and RAM, but it incurs costs as long as it runs.
This is especially relevant for ML workloads, which might need a lot of
resources during training and training might not happen continuously.</p>

<p>For example, maybe our high spender model needs to be trained every
month to predict next month's marketing campaign targets. It would be
wasteful to keep a VM running all the time if we only need it one day of
the month. Of course, we could manually turn it on or off, but Azure
Machine Learning gives us an even better option - compute targets.</p>

<blockquote>
<p>A <em>compute target</em> specifies a compute resource on which we want to
run our ML. This includes the maximum number of nodes and the VM size.</p>
</blockquote>

<p>As a reminder, Azure has a set of defined VM sizes, each with different
performance characteristics and associated costs.<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup> A compute target
specifies which VM type and how many instances we'll need, but it
won't provision the resources until we run a model and request this
target. Once the model run finishes, the resources are deprovisioned.
This makes Azure Machine Learning compute elastic: resources are
allocated when needed, then freed up automatically. We only pay for what
we use, and the service takes care of all the underlying infrastructure.</p>

<p>Let's specify a compute target for our example. We'll request, at
most, one node, use the economical <code>STANDARD_D1_V2</code> VM size (1 CPU, 3.5
GiB memory), and name it <code>d1compute</code>. The following listing shows the
corresponding Azure CLI command:</p>
<div class="highlight"><pre><span/><span class="n">az</span> <span class="n">ml</span> <span class="n">computetarget</span> <span class="n">create</span> <span class="n">amlcompute</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-max-nodes</span> <span class="n">1</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-name</span> <span class="s2">"d1compute"</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-vm-size</span> <span class="n">STANDARD_D1_V2</span> <span class="p">`</span>  
<span class="p">-</span><span class="n">-workspace-name</span> <span class="n">aml</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-resource-group</span> <span class="n">aml-rg</span>
</pre></div>

<p>This won't cost us anything until we actually run a ML workload. If you
click through the UI to the Compute section and navigate to Compute
Clusters, you should see the new definition. Other compute options in
AML are compute instances that include:</p>

<ul>
<li>VMs preimaged with common ML tools and libraries.</li>
<li>Inference clusters, where we can package and deploy models on
Kunbernetes and expose these as REST endpoints.</li>
<li>Attached compute the enables us to target compute resources like
Azure Data Bricks not managed by Azure Machine Learning.</li>
</ul>

<p>Let's move on to storage now. We'll see how we can make our input
available to Azure Machine Learning.</p>

<h2>Setting up Azure Machine Learning storage</h2>

<p>We'll start by uploading our <code>input.csv</code> file from the previous section
to an Azure Data Lake Storage (ADLS) account. Let's first create the
account and a filesystem named <code>fs1</code>. In the code samples below, make
sure to replace <code>&lt;Your ADLS account&gt;</code> with an actual name. This name
needs to be unique across Azure, since it becomes part of the URL used
to address the storage account, so we can't hardcode the name in the
example.</p>
<div class="highlight"><pre><span/><span class="n">az</span> <span class="nb">group </span><span class="n">create</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-location</span> <span class="s2">"Central US"</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-name</span> <span class="n">adls-rg</span>

<span class="n">az</span> <span class="n">storage</span> <span class="n">account</span> <span class="n">create</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-name</span> <span class="p">&lt;</span><span class="n">Your</span> <span class="n">ADLS</span> <span class="n">account</span><span class="p">&gt;</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-resource-group</span> <span class="n">adls-rg</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-enable-hierarchical-namespace</span> <span class="n">true</span>

<span class="n">az</span> <span class="n">storage</span> <span class="n">fs</span> <span class="n">create</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-account-name</span> <span class="p">&lt;</span><span class="n">Your</span> <span class="n">ADLS</span> <span class="n">account</span><span class="p">&gt;</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-name</span> <span class="n">fs1</span>
</pre></div>

<p>The first command creates a new resource group named <code>adls-rg</code>. The
second command provisions an Azure Data Lake Storage Gen2 account in the
resource group. The last command creates a filesystem named <code>fs1</code> in the
storage account.</p>

<p>Let's now upload the <code>input.csv</code> file created in part 1 to the
filesystem. For this, we'll use the Azure CLI upload command to upload
our input file under the <code>models/highspenders/input.csv</code> path. The next
listing shows the commands.</p>
<div class="highlight"><pre><span/><span class="n">az</span> <span class="n">storage</span> <span class="n">fs</span> <span class="n">file</span> <span class="n">upload</span> <span class="p">`</span>
<span class="p">-</span><span class="o">-file</span><span class="n">-system</span> <span class="n">fs1</span> <span class="p">`</span> 
<span class="p">-</span><span class="n">-path</span> <span class="s2">"models/highspenders/input.csv"</span> <span class="p">`</span> 
<span class="p">-</span><span class="n">-source</span> <span class="n">input</span><span class="p">.</span><span class="n">csv</span> <span class="p">`</span> 
<span class="p">-</span><span class="n">-account-name</span> <span class="p">&lt;</span><span class="n">Your</span> <span class="n">ADLS</span> <span class="n">account</span><span class="p">&gt;</span>
</pre></div>

<p>In practice, we would have various Azure Data Factory pipelines copying
datasets to our storage layers. From there, we would need to make these
datasets available to Azure Machine Learning. We'll do this by
attaching a datastore.</p>

<blockquote>
<p>An Azure Machine Learning <em>datastore</em> enable us to connect to an
external storage account like Azure's Blob Storage, Data Lake, SQL,
Databricks, etc., making it available to our ML models.</p>
</blockquote>

<p>First, we need to provision a service principal that Azure Machine
Learning can use to authenticate. We will create a new service principal
in Azure Active Directory (AAD) and grant it Storage Blob Data
Contributor rights on the data lake. This allows the service principal
to read and write data in the data lake. The following listing shows the
steps.</p>
<div class="highlight"><pre><span/><span class="nv">$sp</span> <span class="p">=</span> <span class="n">az</span> <span class="n">ad</span> <span class="nb">sp </span><span class="n">create-for-rbac</span> <span class="p">|</span> <span class="nb">ConvertFrom-Json</span>

<span class="nv">$acc</span> <span class="p">=</span> <span class="n">az</span> <span class="n">storage</span> <span class="n">account</span> <span class="n">show</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-name</span> <span class="p">&lt;</span><span class="n">Your</span> <span class="n">ADLS</span> <span class="n">account</span><span class="p">&gt;</span> <span class="p">|</span> <span class="nb">ConvertFrom-Json</span>

<span class="n">az</span> <span class="n">role</span> <span class="n">assignment</span> <span class="n">create</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-role</span> <span class="s2">"Storage Blob Data Contributor"</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-assignee</span> <span class="nv">$sp</span><span class="p">.</span><span class="n">appId</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-scope</span> <span class="nv">$acc</span><span class="p">.</span><span class="n">id</span>
</pre></div>

<p>The first command creates a principal stored in <code>$sp</code> for role-base
access control (RBAC). The second command retrieves the details of the
Azure Data Lake Storage account and stores it in <code>$acc</code>. The last
command creates a new role assignment, granting read/write access on the
storage account to the service principal we just created.</p>

<p>The service principal can now access data in the storage account. The
next step is to attach the account to Azure Machine Learning, giving it
the service principal ID and secret so it can use these to connect to
the account. The following listing shows how to do this.</p>
<div class="highlight"><pre><span/><span class="n">az</span> <span class="n">ml</span> <span class="n">datastore</span> <span class="n">attach-adls-gen2</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-account-name</span> <span class="p">&lt;</span><span class="n">Your</span> <span class="n">ADLS</span> <span class="n">account</span><span class="p">&gt;</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-client-id</span> <span class="nv">$sp</span><span class="p">.</span><span class="n">appId</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-client-secret</span> <span class="nv">$sp</span><span class="p">.</span><span class="n">password</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-tenant-id</span> <span class="nv">$sp</span><span class="p">.</span><span class="n">tenant</span> <span class="p">`</span> 
<span class="p">-</span><span class="o">-file</span><span class="n">-system</span> <span class="n">fs1</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-name</span> <span class="n">MLData</span> 
<span class="p">-</span><span class="n">-workspace-name</span> <span class="n">aml</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-resource-group</span> <span class="n">aml-rg</span>
</pre></div>

<p>This attaches an Azure Data Lake Storage Gen2 datastore to Azure Machine
Learning, using a service principal to authenticate. We need to supply
the data lake account, the service principal ID, secret, and tenant, the
filesystem we want to attach, and the name we want to give it in Azure
Machine Learning (<code>MLData</code> in our case).</p>

<p>Now if you navigate to the Storage section in the UI, you should see the
newly created <code>MLData</code> datastore. In fact, you should see a couple more
datastores that are created by default and used within the workspace. In
practice, we need to connect to external storage, and data stores are
the way to do that.</p>

<p>Our workspace is now configured with both a compute target and an
attached data store. Let's grant our service, <code>principalContributor</code>,
rights to the Azure Machine Learning workspace too, so we can use it for
deployment. Note, in a production environment, we would have separate
service principals for better security, then if one of the principals
gets compromised, it has access to fewer resources. We'll reuse our
<code>$sp</code> service principal, though, to keep things brief. The following
listing shows how to grant the rights.</p>
<div class="highlight"><pre><span/><span class="nv">$aml</span> <span class="p">=</span> <span class="n">az</span> <span class="n">ml</span> <span class="n">workspace</span> <span class="n">show</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-workspace-name</span> <span class="n">aml</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-resource-group</span> <span class="n">aml-rg</span> <span class="p">`</span>
<span class="p">|</span> <span class="nb">ConvertFrom-Json</span>  

<span class="n">az</span> <span class="n">role</span> <span class="n">assignment</span> <span class="n">create</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-role</span> <span class="s2">"Contributor"</span> <span class="p">`</span> 
<span class="p">-</span><span class="n">-assignee</span> <span class="nv">$sp</span><span class="p">.</span><span class="n">appId</span> <span class="p">`</span>
<span class="p">-</span><span class="n">-scope</span> <span class="nv">$aml</span><span class="p">.</span><span class="n">id</span>
</pre></div>

<p>The first command gets the details of an Azure Machine Learning
workspace and stores them in the <code>$aml</code> variable. The second command
creates a role assignment, granting the Contributor role to the service
principal <code>$sp</code> on the workspace.</p>

<p>We'll also store the service principal's password in an environment
variable so that we can read it without having to embed it into the
code. The following listing shows how to set an environment variable in
a PowerShell session. This won't get persisted across sessions, so make
a note of <code>$sp.password</code>.</p>
<div class="highlight"><pre><span/><span class="nv">$env:SP_PASSWORD</span> <span class="p">=</span> <span class="nv">$sp</span><span class="p">.</span><span class="n">password</span>
</pre></div>

<p>The name <em>password</em> is a bit misleading. This is an autogenerated client
secret that was created when we ran <code>az ad sp create-for-rbac</code> (which
stands for <q>Azure Active Directory service principal create for
role-based access control</q>). We are all set. The next step is to
publish our Python code and run it in the cloud. We will do that in part
3.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>For more on VM sizes and costs, see
<a href="https://docs.microsoft.com/en-us/azure/virtual-machines/sizes">https://docs.microsoft.com/en-us/azure/virtual-machines/sizes</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Fri, 17 Sep 2021 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/09/10/machine-learning-on-azure-part-1.html</link>
      <guid>https://vladris.com/blog/2021/09/10/machine-learning-on-azure-part-1.html</guid>
      <title><![CDATA[Machine Learning on Azure - Part 1]]></title>
      <description><![CDATA[<h1>Machine Learning on Azure - Part 1</h1>

<p>This is an excerpt from chapter 7 of my book, <a href="https://www.manning.com/books/azure-data-engineering">Data Engineering on
Azure</a>, which
deals with machine learning workloads. This will be a series of 3 posts.
In this post, we'll create a simple ML model in Python. In the next
post, we'll go over Azure Machine Learning. In the final post, we'll
run this model in Azure Machine Learning. Let's start with the simple
ML model.</p>

<h2>Training a machine learning model</h2>

<p>This model predicts whether a user is likely to be a high spender, based
on the number of sessions and page views on our website. A session is a
website visit in which the user views one or more pages. Let's assume
that the amount of money a user spends on our products is correlated to
the number of sessions and page views. We'll consider a user a high
spender if they spend $30 or more.</p>

<p>The following table shows our input data: the user's ID, the number of
sessions, the number of page views, the amount of dollars spent, and
whether we consider the user a high spender.</p>

<table>
<thead>
<tr>
<th style="text-align: right">User ID</th>
<th style="text-align: right">Sessions</th>
<th style="text-align: right">Page views</th>
<th style="text-align: right">Total spent</th>
<th style="text-align: center">High spender</th>
</tr>
</thead>

<tbody>
<tr>
<td style="text-align: right">1</td>
<td style="text-align: right">10</td>
<td style="text-align: right">45</td>
<td style="text-align: right">100</td>
<td style="text-align: center">Yes</td>
</tr>
<tr>
<td style="text-align: right">2</td>
<td style="text-align: right">5</td>
<td style="text-align: right">10</td>
<td style="text-align: right">30</td>
<td style="text-align: center">Yes</td>
</tr>
<tr>
<td style="text-align: right">3</td>
<td style="text-align: right">1</td>
<td style="text-align: right">5</td>
<td style="text-align: right">10</td>
<td style="text-align: center">No</td>
</tr>
<tr>
<td style="text-align: right">4</td>
<td style="text-align: right">2</td>
<td style="text-align: right">2</td>
<td style="text-align: right">0</td>
<td style="text-align: center">No</td>
</tr>
<tr>
<td style="text-align: right">5</td>
<td style="text-align: right">9</td>
<td style="text-align: right">33</td>
<td style="text-align: right">95</td>
<td style="text-align: center">Yes</td>
</tr>
<tr>
<td style="text-align: right">6</td>
<td style="text-align: right">7</td>
<td style="text-align: right">5</td>
<td style="text-align: right">5</td>
<td style="text-align: center">No</td>
</tr>
<tr>
<td style="text-align: right">7</td>
<td style="text-align: right">19</td>
<td style="text-align: right">31</td>
<td style="text-align: right">95</td>
<td style="text-align: center">Yes</td>
</tr>
<tr>
<td style="text-align: right">8</td>
<td style="text-align: right">1</td>
<td style="text-align: right">20</td>
<td style="text-align: right">0</td>
<td style="text-align: center">No</td>
</tr>
<tr>
<td style="text-align: right">9</td>
<td style="text-align: right">2</td>
<td style="text-align: right">17</td>
<td style="text-align: right">0</td>
<td style="text-align: center">No</td>
</tr>
<tr>
<td style="text-align: right">10</td>
<td style="text-align: right">8</td>
<td style="text-align: right">25</td>
<td style="text-align: right">40</td>
<td style="text-align: center">Yes</td>
</tr>
</tbody>
</table>

<p>The listing shows the input CSV file corresponding to the table that
we'll use for training, <code>input.csv</code>.</p>
<div class="highlight"><pre><span/>UserId,Sessions,PageViews,TotalSpend,HighSpender 
1,10,45,100,Yes 
2,5,10,30,Yes 
3,1,5,10,No 
4,2,2,0,No 
5,9,33,95,Yes 
6,7,5,5,No 
7,19,31,95,Yes 
8,1,20,0,No 
9,2,17,0,No 
10,8,25,40,Yes
</pre></div>

<p>You need to create this file on your machine as <code>input.csv</code>. We are
working with simple input and a simple model because our focus is taking
a model and putting it into production, not in building the model
itself. There are plenty of great references covering model development
and ML if you are interested in the topic.</p>

<p>Assuming you already have Python on your machine, let's start by
installing the two packages we need for our model: <code>pandas</code> and
<code>scikit-learn</code> (also known as <code>sklearn</code>). The following listing shows
the command to install these packages using the Python package manager,
<code>pip</code>. If you don't have Python, you can install it from
<a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a>.</p>
<div class="highlight"><pre><span/>pip<span class="w"> </span>install<span class="w"> </span>pandas<span class="w"> </span>sklearn
</pre></div>

<p>Now that we have our input file and packages, let's look at the high
spender model itself. Don't worry if you haven't implemented a ML
model before; our model has only a few lines of code and is very basic.
We'll walk through the steps that should give you at least a high-level
understanding.</p>

<h2>Training a model using Scikit-learn</h2>

<p>Our model takes an <code>--input &lt;file&gt;</code> argument, representing the input
CSV. It reads this file into a Pandas DataFrame.</p>

<blockquote>
<p>A <em>DataFrame</em> is a fancy table data structure offered by the Pandas
library. It provides various useful ways to slice and dice the data.</p>
</blockquote>

<p>We'll split the data into the features used to train the model (<em>X</em>)
and what we are trying to predict (<em>y</em>). In our case, we will take the
Sessions and PageViews columns from the input as <em>X</em>, and the
HighSpender column as <em>y</em>. This model doesn't care about user ID and
the exact amount spent, so we can ignore those columns.</p>

<p>We will split our input data so that we take 80% of it to train the
model and use the remaining 20% to test our model. For the 20%, we will
use the model to predict whether the user is a high spender and see how
our prediction compares with the actual data. This is a common practice
for measuring model prediction accuracy.</p>

<p>We will use <code>KNeighborsClassifier</code> from <code>scikit-learn</code>. This implements
a well-known classification algorithm, the k-nearest neighbors vote. We
use a classification algorithm because we want to classify our users
into high spenders and non-high spenders. We won't cover the details of
the algorithm here, but the good news is that this is fully encapsulated
in the <code>scikit-learn</code> library so we can create it with one line of code
and train it with a second line of code. We will use the training data
to train the model, then try to predict on the test data and print the
predictions. The figure shows these steps:</p>

<p><img src="https://vladris.com/blog/2021/09/10/steps.png" alt="image"/></p>

<p>Steps for training our model:</p>

<ol>
<li>Extract features and target the value from the input.</li>
<li>Split the dataset into train and test data.</li>
<li>Train the model on the training data.</li>
<li>Use the model to predict on the test data, comparing predictions
with actual data.</li>
</ol>

<p>Finally, we will save the model on disk as <code>outputs/highspender.pkl</code>.
The idea is that once we have a trained model, another system picks it
up and uses it to predict new data. For example, as users visit our
website, we can use the model to predict who is likely to be a high
spender and maybe offer them a discount. Or maybe we want to encourage
non-high spenders to spend more time on the website, hoping it converts
them into high spenders. Either way, some other service has to load this
model and feed it never-before-seen data, and the model will predict if
the user is likely to be a high spender or not.</p>

<h2>High spender model implementation</h2>

<p>Training a model might sound like a lot, but it is only 25 lines of
Python code as the following listing shows:</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">argparse</span> 
<span class="kn">from</span><span class="w"> </span><span class="nn">joblib</span><span class="w"> </span><span class="kn">import</span> <span class="n">dump</span> 
<span class="kn">import</span><span class="w"> </span><span class="nn">os</span> 
<span class="kn">import</span><span class="w"> </span><span class="nn">pandas</span><span class="w"> </span><span class="k">as</span><span class="w"> </span><span class="nn">pd</span> 
<span class="kn">from</span><span class="w"> </span><span class="nn">sklearn.neighbors</span><span class="w"> </span><span class="kn">import</span> <span class="n">KNeighborsClassifier</span>  
<span class="kn">from</span><span class="w"> </span><span class="nn">sklearn.model_selection</span><span class="w"> </span><span class="kn">import</span> <span class="n">train_test_split</span>  

<span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">()</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">'--input'</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s1">'model_input'</span><span class="p">)</span>

<span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> 
<span class="n">model_input</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">model_input</span>
<span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="n">model_input</span><span class="p">)</span>

<span class="n">X</span> <span class="o">=</span> <span class="n">df</span><span class="p">[[</span><span class="s2">"Sessions"</span><span class="p">,</span> <span class="s2">"PageViews"</span><span class="p">]]</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s2">"HighSpender"</span><span class="p">]</span>

<span class="n">X_train</span><span class="p">,</span> <span class="n">X_test</span><span class="p">,</span> <span class="n">y_train</span><span class="p">,</span> <span class="n">y_test</span> <span class="o">=</span> <span class="n">train_test_split</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span>
  <span class="n">test_size</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>

<span class="n">knn</span> <span class="o">=</span> <span class="n">KNeighborsClassifier</span><span class="p">()</span>
<span class="n">knn</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X_train</span><span class="p">,</span> <span class="n">y_train</span><span class="p">)</span>

<span class="n">score</span> <span class="o">=</span> <span class="n">knn</span><span class="o">.</span><span class="n">predict</span><span class="p">(</span><span class="n">X_test</span><span class="p">)</span>

<span class="n">predictions</span> <span class="o">=</span> <span class="n">X_test</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">deep</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">predictions</span><span class="p">[</span><span class="s2">"Prediction"</span><span class="p">]</span> <span class="o">=</span> <span class="n">score</span>
<span class="n">predictions</span><span class="p">[</span><span class="s2">"Actual"</span><span class="p">]</span> <span class="o">=</span> <span class="n">y_test</span>

<span class="nb">print</span><span class="p">(</span><span class="n">predictions</span><span class="p">)</span>

<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="s1">'outputs'</span><span class="p">):</span> <span class="n">os</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="s1">'outputs'</span><span class="p">)</span>  

<span class="n">model_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">'outputs'</span><span class="p">,</span> <span class="s1">'highspender.pkl'</span><span class="p">)</span>
<span class="n">dump</span><span class="p">(</span><span class="n">knn</span><span class="p">,</span> <span class="n">model_path</span><span class="p">)</span>
</pre></div>

<p>We'll save this Python script as <code>highspenders.py</code>.</p>

<p>Let's break it down and explain each step. First, we import all the
libraries we need. Next, we set up command line argument parsing to
expect an <code>--input</code> argument:</p>
<div class="highlight"><pre><span/><span class="n">parser</span> <span class="o">=</span> <span class="n">argparse</span><span class="o">.</span><span class="n">ArgumentParser</span><span class="p">()</span>
<span class="n">parser</span><span class="o">.</span><span class="n">add_argument</span><span class="p">(</span><span class="s1">'--input'</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="nb">str</span><span class="p">,</span> <span class="n">dest</span><span class="o">=</span><span class="s1">'model_input'</span><span class="p">)</span>
</pre></div>

<p>We then grab the input file path from the command line argument and load
the file into a Pandas DataFrame:</p>
<div class="highlight"><pre><span/><span class="n">args</span> <span class="o">=</span> <span class="n">parser</span><span class="o">.</span><span class="n">parse_args</span><span class="p">()</span> 
<span class="n">model_input</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">model_input</span>
<span class="n">df</span> <span class="o">=</span> <span class="n">pd</span><span class="o">.</span><span class="n">read_csv</span><span class="p">(</span><span class="n">model_input</span><span class="p">)</span>
</pre></div>

<p>Then we define the model inputs as the Sessions and PageViews columns
and the output (prediction) as the HighSpender column:</p>
<div class="highlight"><pre><span/><span class="n">X</span> <span class="o">=</span> <span class="n">df</span><span class="p">[[</span><span class="s2">"Sessions"</span><span class="p">,</span> <span class="s2">"PageViews"</span><span class="p">]]</span>
<span class="n">y</span> <span class="o">=</span> <span class="n">df</span><span class="p">[</span><span class="s2">"HighSpender"</span><span class="p">]</span>
</pre></div>

<p>Next, we split the input data into training data and data reserved for
testing using a 0.2 ratio:</p>
<div class="highlight"><pre><span/><span class="n">X_train</span><span class="p">,</span> <span class="n">X_test</span><span class="p">,</span> <span class="n">y_train</span><span class="p">,</span> <span class="n">y_test</span> <span class="o">=</span> <span class="n">train_test_split</span><span class="p">(</span><span class="n">X</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span>
    <span class="n">test_size</span><span class="o">=</span><span class="mf">0.2</span><span class="p">,</span> <span class="n">random_state</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</pre></div>

<p>We select the <code>KNeighborsClassifier</code> with default settings:</p>
<div class="highlight"><pre><span/><span class="n">knn</span> <span class="o">=</span> <span class="n">KNeighborsClassifier</span><span class="p">()</span>
</pre></div>

<p>Then we train the model on the training data:</p>
<div class="highlight"><pre><span/><span class="n">knn</span><span class="o">.</span><span class="n">fit</span><span class="p">(</span><span class="n">X_train</span><span class="p">,</span> <span class="n">y_train</span><span class="p">)</span>
</pre></div>

<p>Next, we set the prediction score using the trained model on the test
data:</p>
<div class="highlight"><pre><span/><span class="n">score</span> <span class="o">=</span> <span class="n">knn</span><span class="o">.</span><span class="n">predict</span><span class="p">(</span><span class="n">X_test</span><span class="p">)</span>
</pre></div>

<p>We then format the output, copying it into a new DataFrame and adding
Prediction and Actual columns:</p>
<div class="highlight"><pre><span/><span class="n">predictions</span> <span class="o">=</span> <span class="n">X_test</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">deep</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="n">predictions</span><span class="p">[</span><span class="s2">"Prediction"</span><span class="p">]</span> <span class="o">=</span> <span class="n">score</span>
<span class="n">predictions</span><span class="p">[</span><span class="s2">"Actual"</span><span class="p">]</span> <span class="o">=</span> <span class="n">y_test</span>
</pre></div>

<p>Finally, we print the predictions to the console, ensure we have an
<code>outputs/</code> directory, and save the model as <code>outputs/highspender.pkl</code>:</p>
<div class="highlight"><pre><span/><span class="nb">print</span><span class="p">(</span><span class="n">predictions</span><span class="p">)</span>

<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isdir</span><span class="p">(</span><span class="s1">'outputs'</span><span class="p">):</span> <span class="n">os</span><span class="o">.</span><span class="n">mkdir</span><span class="p">(</span><span class="s1">'outputs'</span><span class="p">)</span>  

<span class="n">model_path</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="s1">'outputs'</span><span class="p">,</span> <span class="s1">'highspender.pkl'</span><span class="p">)</span>
<span class="n">dump</span><span class="p">(</span><span class="n">knn</span><span class="p">,</span> <span class="n">model_path</span><span class="p">)</span>
</pre></div>

<p>Let's run the script and check the output. The following listing shows
the console command for running the model:</p>
<div class="highlight"><pre><span/>python<span class="w"> </span>highspenders.py<span class="w"> </span>--input<span class="w"> </span>input.csv
</pre></div>

<p>You should see the test predictions and actual data printed to the
console. You should also now see the <code>outputs/highspender.pkl</code> model
file. Strictly speaking, we don't need the prediction and printing
part, but it should help if we want to play with the model.</p>

<p>Here, we're using a small input size. The larger the input dataset, the
better the accuracy. But again, our focus is taking this Python script
and running it in the cloud. The good news is that our approach to
DevOps (or MLOps) scales to more complex models and larger inputs. In
the next post, we'll look at Azure Machine Learning, the Azure PaaS
(platform as a service) offering for running ML in the cloud. We'll
then connect the dots and get this model running in Azure Machine
Learning in part 3.</p>
]]></description>
      <pubDate>Fri, 10 Sep 2021 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/08/12/shipping-a-feature.html</link>
      <guid>https://vladris.com/blog/2021/08/12/shipping-a-feature.html</guid>
      <title><![CDATA[Shipping a Feature]]></title>
      <description><![CDATA[<h1>Shipping a Feature</h1>

<p>I recently did a small presentation for my team talking about what it
takes to ship a feature to customers in a product like Office. This
includes much more than getting the functionality implemented and
tested. In fact, figuring out the design and implementing it accounts
for about 20% of the work (from prototype to implementation, including
tests). The remaining 80% is taking the feature from <em>functional</em> to
<em>shippable</em>. In this post, I'll go over some of these non-functional
aspects of shipping code to customers.</p>

<p>Most of the aspects I will talk about rely heavily on telemetry. This is
a consequence of today's connected world. Software is shipped over the
internet every month or every week (or every day), as opposed to every
year or every other year. Connectivity also enables us to get signals on
how the software is performing and adjust accordingly.</p>

<h2>Reliability</h2>

<p>Reliability can make or break a feature. It is the bedrock of quality.
If the feature is unreliable and causes crashes or data corruption,
nobody will use it. The most egregious of reliability issues is data
loss - for example, if a user writes a paragraph and the application
crashes before this paragraph gets saved anywhere, forcing the user to
re-type it causes a huge loss of trust.</p>

<p>In terms of software engineering, beyond comprehensive testing, we need
to have telemetry in place to report errors. There are several ways to
quantify reliability. For example, a couple of common measures are the
<em>ICE</em> and <em>ACE</em> scores.</p>

<p><em>ICE</em> stands for <em>Ideal Customer Experience</em>. This measures the
reliability of a scenario including all errors encountered during a
user's session. 100% means no session encountered any errors.</p>

<p><em>ACE</em> stands for <em>Adjusted Customer Experience</em>. This is similar to ICE,
except it only measures unexpected errors. In a complex system, some
errors are expected, and the software can recover from them without
impacting the user experience. For example, a background call fails but
succeeds on retry.</p>

<p>Both measures are important - one measures the overall reliability of
the system, the other measures the user experience impact.</p>

<p>100% ICE and ACE scores are ideal, but hard to achieve in a complex
system. That said, shipping a feature should include setting a target
ICE and ACE score (for example 99%), making sure telemetry is there to
provide the signal, and working towards that goal as the feature gets
exposed to more and more users (more on exposure below).</p>

<h2>Performance</h2>

<p>Performance is another fundamental aspect of any feature. Of course, the
first rule of performance tuning is to measure. Shipping a feature
includes instrumentation to measure various scenarios like time to load,
time to render etc. Customers run the code on different types of
hardware, and it is important to understand what the actual user
experience is (in the 95th percentile).</p>

<p>Like reliability, we should set some goals, look at telemetry, and keep
improving. Important to note that this is not a one-time thing, as
software gets updated and functionality is added, performance can easily
degrade. Performance numbers should show up on a dashboard and should be
reviewed periodically.</p>

<h2>Security</h2>

<p>Microsoft created the <a href="https://www.microsoft.com/en-us/securityengineering/sdl/">Security Development
Lifecycle</a> for
building better, safer, software internally. In 2008, this was shared
with the rest of the world and it continues evolving. I won't cover all
security best practices as it would take way more than a blog post, but
I will touch on a few points:</p>

<ul>
<li><p><a href="https://www.microsoft.com/en-us/securityengineering/sdl/threatmodeling">Threat
modeling</a>
- non-trivial features should have a threat model - a data flow
diagram which captures the various entities in the system and the
trust boundaries. The Microsoft Threat Modeling Tool can analyze a
threat model and list out potential attacks and suggested
mitigations.</p></li>
<li><p>Adhering to standards and best practices - for example always
connecting over HTTPS instead of HTTP, using cryptographically
strong algorithms and so on.</p></li>
<li><p>Leveraging available tools to ensure a feature is secure. For
example, running static code analysis to identify potential attack
vectors and <a href="https://en.wikipedia.org/wiki/Fuzzing">fuzzing</a> inputs.</p></li>
</ul>

<p>The bar for security should be very high, and a feature should never
roll out to customers before ensuring it is secure.</p>

<h2>Privacy</h2>

<p>Customer privacy is extremely important. If our feature handles any
customer data (data about the customer) or customer-owned data (data
generated by the customer), we need to be very careful how we process
it, store it, and who can access it. I talked extensively about data
handling in my previous blog post, <a href="https://vladris.com/blog/2020/11/27/changing-data-classification-through-processing.html">Changing Data Classification Through
Processing</a>.</p>

<h2>Compliance</h2>

<p>Compliance ensures we don't open ourselves up to liability. An example
of this is third party notices for open-source libraries - many
open-source licenses require you to mention you are using the library.
Another example is GDPR compliance - EU citizens can request to view all
the data a company has on them, or request to be <q>forgotten</q> (have
their data removed from the system).</p>

<p>Compliance also means our software adheres to various standards some
customers might require. An example of this is data sovereignty:
countries like Germany and China require data to be stored in data
centers within their country. Another example is ensuring our software
meets the requirements for certain certifications like SOC2, without
which certain organizations wouldn't be able to use it.</p>

<p>Our feature needs to be compliant before shipping it to customers.</p>

<h2>Accessibility</h2>

<p>The Microsoft mission statement reads as follows:</p>

<blockquote>
<p><em>Our mission is to empower every person and every organization on the
planet to achieve more.</em></p>
</blockquote>

<p>Making our software accessible to people with disabilities is very
important. Here are a few aspects we need to consider when shipping
features users interact with:</p>

<ul>
<li>Contrast ratio - the contrast between foreground colors and
background colors needs to be good enough so everything is legible
for people with vision impairment.</li>
<li>High contrast - operating systems provide high-contrast modes for
the visually impaired. Features need to be tested in high-contrast
mode to ensure they are still usable.</li>
<li>Screen reader support - UI elements need to be annotated so screen
reader software can describe them correctly.</li>
<li>Keyboarding - some users navigate exclusively using keyboard
shortcuts, so a feature needs to implement common keyboard shortcuts.</li>
<li>Focus - a feature needs to properly handle focus switching. This
includes tab order, making sure focus doesn't get trapped on a
single control or subset of the controls etc.</li>
<li>Touch - touchscreen devices without keyboard usually have larger
touch targets. We need to make sure our feature works well on
touchscreens too.</li>
</ul>

<h2>World readiness</h2>

<p>World readiness means our feature can ship in markets across the world,
and usually entails two different aspects: <em>globalization</em> and
<em>localization</em>.</p>

<p>Globalization means our feature works in different cultures, with
different (OS-level) culture settings, without requiring additional,
culture-specific changes. An example is the date format. In US, the date
format is <code>mm-dd-yyyy</code>, while in Europe it is <code>dd-mm-yyyy</code>. Japan uses
<code>yyyy-mm-dd</code>. When displaying dates, we should format them using the
current culture's format, not assume and hardcode any specific format.</p>

<p>Another important aspect of globalization is to ensure the symbols used
as icons make sense for everyone. For example, using a starry wizard hat
to represent a setup wizard works in Western cultures but might not make
sense all around the world.</p>

<p>Localization deals with translating UI strings into all the languages in
which the feature ships. From a developer perspective, UI layout is
important here: in some languages, words are on average longer than in
English, so text might overflow its boundaries when translated. For
example, <q>Add job</q> in English becomes <q>Auftrag hinzufÃ¼gen</q> in
German.</p>

<p>We also have right-to-left languages like Arabic and Hebrew. We need to
ensure our layout works as expected in such languages.</p>

<h2>Feature gating</h2>

<p>In a mature product like Office, making changes feels very much like
rebuilding an airplane in flight: we can add and modify features, but
breaking anything is catastrophic. One best practice of shipping
features in such conditions is using feature gates. A feature gate is a
toggle that determines whether a code path should be exercised or not.
This allows us to release a build containing a half-developed feature.
If it is not quite ready to see the light of day, the feature gate is
closed, and the code never runs in production.</p>

<p>Once the feature is ready, we can toggle the feature gate and start
running the code. In case we notice any issues, we can flip the feature
gate back off and mitigate customer impact while the issue gets
resolved.</p>

<p>Once the feature is mature and has been exercised by customers for a
while, we can go back and clean up the feature gate.</p>

<h2>Flighting</h2>

<p>Feature gates are a simple on/off switch. Flighting changes is a more
mature version of progressive exposure. We usually have a set of rings
through which we release. For example, we could have a dogfood ring, for
the team to try out the code themselves, before shipping further; we
could have a beta tester ring, for customers who sign up to get preview
features; finally, we could have a production ring, containing all other
customers.</p>

<p>We should be able to progress a feature through these different rings,
and within the rings, only expose a percentage of customers to the
feature.</p>

<p>Flighting infrastructure needs to exist for this. From a feature
development perspective, we need a roll out plan defining what telemetry
signals we want to see to be comfortable increasing exposure of our
feature.</p>

<h2>Experimentation</h2>

<p>Finally, we need a way to measure whether a feature is successful or not
and determine whether iterating on it improves things or makes them
worse. First, we need to define what success means - what metrics are
most important for our product. Once we have these, we can run an A/B
test when introducing a new feature or iterating on an existing feature.
We have a control group seeing the old behavior and a treatment group
seeing the new behavior. We can then look at the key metrics we defined
and see how they look for both control and treatment. Did the new code
move the needle?</p>

<h2>Summary</h2>

<p>Shipping a feature takes a lot of work beyond the initial functional
implementation. In this post we looked at some of these various aspects:</p>

<ul>
<li>Reliability</li>
<li>Performance</li>
<li>Security</li>
<li>Privacy</li>
<li>Compliance</li>
<li>Accessibility</li>
<li>World readiness</li>
<li>Feature gating</li>
<li>Flighting</li>
<li>Experimentation</li>
</ul>

<p>All of these need to be taken into account when we ship code to our
customers.</p>
]]></description>
      <pubDate>Thu, 12 Aug 2021 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/06/21/data-engineering-on-azure-rtm.html</link>
      <guid>https://vladris.com/blog/2021/06/21/data-engineering-on-azure-rtm.html</guid>
      <title><![CDATA[Data Engineering on Azure RTM]]></title>
      <description><![CDATA[<h1>Data Engineering on Azure RTM</h1>

<p>My book, <a href="https://www.manning.com/books/data-engineering-on-azure">Data Engineering on
Azure</a>, which I
announced in <a href="https://vladris.com/blog/2020/10/08/azure-data-engineering.html">this blog
post</a>,
is going to print soon. As I did with my previous book, <a href="https://vladris.com/blog/2019/10/16/programming-with-types-rtm.html">Programming
with
Types</a>,
I'm writing another <q>RTM</q> post to talk about a few aspects of the
process.</p>

<h2>Title evolution</h2>

<p>When I pitched the book to Manning, I used the title <em>Production Data
Engineering with Azure</em>. The title was supposed to capture that this is
a book about the practical aspects of data engineering, with examples on
the Azure platform. In fact, here is how I described the book's topic
in the proposal:</p>

<blockquote>
<p>The same way Software Engineering brings engineering rigor to software
development, Data Engineering aims to bring rigor to working with data
in a reliable way.</p>

<p>This book is about implementing the various aspects of a big data
platform - data ingestion, running analytics and ML, distributing
data - in a real-world production system. The focus is on operational
aspects like DevOps, monitoring, scale, and compliance. Examples will
be provided using Azure services.</p>

<p>There is a big gap between what it takes, for example, to implement an
ML model in Python and what it takes to run in a production
environment, on a regular basis, with robust guardrails in place. The
book focuses on the latter, which makes it different than other data
platform books.</p>
</blockquote>

<p>The Manning team has a lot of experience putting together books (and
selling them). We iterated on the title quite a few times, trying to
best capture the essence of the book. Once we started the project, we
changed the name from <em>Production Data Engineering with Azure</em> to
<em>Practical Data Engineering on Azure</em>.</p>

<p>Before launching the book as a Manning Early Access Preview (MEAP), we
changed the name again, this time to <em>Azure Data Engineering</em>: the
<q>Practical</q> part of the title made it a bit too long and not very
clear.</p>

<p>As the manuscript was wrapping up, we took another look at the title:
<em>Azure Data Engineering</em> implies the book is Azure-specific. While all
the examples provided are built in the Azure cloud, my hope is the
patterns and ideas discussed apply to any big data platform, in any
cloud. We iterated on the title again, to emphasize the <q>data
engineering</q> part, and ended up with <em>Data Engineering on Azure</em>. This
is the final title of the book.</p>

<h2>Articles and excerpts</h2>

<p>Before starting the project, I wrote a few articles on the topic. The
first one was <a href="https://vladris.com/blog/2019/12/08/notes-on-data-engineering.html">Notes on Data
Engineering</a>.
Soon after, my team launched the <a href="https://medium.com/data-science-at-microsoft">Data Science @
Microsoft</a> Medium
publication, where I contributed several articles:</p>

<ul>
<li><a href="https://medium.com/data-science-at-microsoft/how-we-built-self-serve-data-environment-tools-with-azure-3951a698fc9d">How we built self-serve data environment tools with
Azure</a>.</li>
<li><a href="https://medium.com/data-science-at-microsoft/azure-data-explorer-at-the-azure-business-scale-89262ef8c1fd">Azure Data Explorer at the Azure business
scale</a>.</li>
<li><a href="https://medium.com/data-science-at-microsoft/running-machine-learning-at-scale-808b90f0ec75">Running machine learning at
scale</a>.</li>
<li><a href="https://medium.com/data-science-at-microsoft/common-data-engineering-challenges-and-their-solution-dd51872812ac">Common data engineering challenges and their
solution</a> -
which is a retake on that first article (Notes on Data Engineering).</li>
<li><a href="https://medium.com/data-science-at-microsoft/partnering-for-data-quality-dc9123557f8b">Partnering for data
quality</a>.</li>
<li><a href="https://medium.com/data-science-at-microsoft/partnering-for-metadata-management-277733911d03">Partnering for metadata
management</a>.</li>
<li><a href="https://medium.com/data-science-at-microsoft/data-distribution-9085b4316591">Data
distribution</a>.</li>
</ul>

<p>Most of the ideas from these articles show up in the book. While the
articles talk about the specific challenges my team encountered and the
solutions we came up with to solve them, the book covers patterns - the
general types of problems you would encounter while building a big data
platform, and solutions you could apply. The articles helped me to
clarify (for myself) the topics I wanted to cover in the book, and
refine the proposed solutions.</p>

<p>Once the manuscript was well underway, I wrote a blog post on <a href="https://vladris.com/blog/2020/11/13/data-quality-testing-patterns.html">Data
Quality Testing
Patterns</a>
to clarify my thoughts as I was working on chapter 9 (Data quality), but
otherwise switched my focus from articles to getting the book done. At
this point, I started publishing excerpts from the book. So far I wrote
about <a href="https://vladris.com/blog/2020/11/27/changing-data-classification-through-processing.html">Changing data classification through
processing</a>
and <a href="https://vladris.com/blog/2021/03/12/ingesting-data.html">Ingesting
data</a>, with
more to come.</p>

<h2>The speed of the cloud</h2>

<p>Innovation in cloud computing moves at a break-neck speed. The
technology changes so fast, it is hard to pin things down in written
form. For setting up various Azure services, I wanted to rely on command
line scripts instead of the Azure Portal UI - walking readers through
series of screenshots is tedious, and UI changes all the time. I used
<a href="https://docs.microsoft.com/en-us/cli/azure/">Azure CLI</a> instead. That
said, many of the extensions I used throughout the book are currently
<q>experimental</q>, which means they might change at a future time. I also
found a couple of bugs I reported to the teams maintaining the Azure CLI
extensions.</p>

<p>Another example of the speed of innovation is <a href="https://azure.microsoft.com/en-us/services/purview/">Azure
Purview</a>. When I
started working on our data platform, there was no Azure Purview and my
team had to develop a home-grown solution to address our data inventory
needs. We then got to use a preview, in-development version of Azure
Purview before it was publicly announced (one of the perks of working at
Microsoft). Chapter 8 of my book covers metadata management, with the
reference implementation on Azure Purview. That meant I wasn't able to
start on this chapter until Azure Purview was officially announced, even
though I knew what I wanted to write about. Things lined up pretty well,
I finished chapter 7 and had to skip to chapter 9, but as I was working
on that, Azure Purview went into public preview.</p>

<p>This was a very interesting experience, very different than my previous
book. Writing my first book, I didn't feel like there were so many
moving parts to get a handle on and the speed with which things changed
wasn't overwhelming. Even so, I'm confident the patterns I cover in
the book will remain the same for quite some time, regardless of the
technologies used to implement them. So even as new services launch and
the ways we interact with the cloud evolve, the key takeaways should
stay relevant.</p>

<p>Check out my book here: <a href="https://www.manning.com/books/data-engineering-on-azure">Data Engineering on
Azure</a>.</p>
]]></description>
      <pubDate>Mon, 21 Jun 2021 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2021/03/12/ingesting-data.html</link>
      <guid>https://vladris.com/blog/2021/03/12/ingesting-data.html</guid>
      <title><![CDATA[Ingesting Data]]></title>
      <description><![CDATA[<h1>Ingesting Data</h1>

<p>This is an excerpt from chapter 2 of my book, <a href="https://www.manning.com/books/azure-data-engineering">Data Engineering on
Azure</a>, which
deals with storage. In this article we'll look at a few aspects of data
ingestion: frequency and load type, and how we can handle corrupted
data. We'll use Azure Data Explorer as the storage solution, but keep
in mind that the same concepts apply regardless of the data fabric used.
Code samples are omitted from this article, though available in the
book. Let's start by looking at the frequency with which we ingest
data.</p>

<h2>Ingestion frequency</h2>

<p>Frequency defines how often we ingest a given dataset. This can range
from continuous ingestion, for streaming data, to yearly ingestion - a
dataset which we only need to ingest once a year. For example, our
website team produces web telemetry which we can, if we want to, ingest
in real time. If our analytics scenarios include some real time or near
real time processing, we can bring the data into our data platform as it
is being generated.</p>

<p>The following figure shows this streaming ingestion setup.</p>

<p><img src="https://vladris.com/blog/2021/03/12/fig1.png" alt="image"/></p>

<p><em>As users visit website pages, each visit is sent as an event to an
Azure Event Hub. Azure Data Explorer ingests data into the PageViews
table in real time.</em></p>

<p>Azure Event Hub is a service that can receive and process millions of
events per second. An event contains some data payload sent by the
client to the Event Hub. A high-traffic website could treat each page
view as an event and pass the user ID, URL, and timestamp to an Even
Hub. From there, data can be routed to various other services. In our
case, it can be ingested in Azure Data Explorer in real time.</p>

<p>Another option, if we don't have any real time requirements, is to
ingest the data on some regular cadence, for example every midnight we
load the logs for the day.</p>

<p>The following figure shows this alternative setup.</p>

<p><img src="https://vladris.com/blog/2021/03/12/fig2.png" alt="image"/></p>

<p><em>Logs get copied from the website Azure Data Explorer cluster to our
Azure Data Explorer cluster using an Azure Data Factory. Copy happens on
a daily basis.</em></p>

<p>In this case, the website team stores its logs into a dedicated Azure
Data Explorer cluster. Their cluster only stores data for the past 30
days since it is used just to measure the website performance and debug
issues. Since we want to keep data for longer for analytics, we want to
copy it to our cluster and preserve it there.</p>

<p>Azure Data Factory is the Azure ETL service, which enables serverless
data integration and transformation. We can use a Data Factory to
coordinate when and where data gets moved. In our case, we copy the logs
of the previous day every night and append them to our <code>PageViews</code>
table.</p>

<p>Let's take another example: the sales data from our Payments team. We
use this data to measure revenue and other business metrics. Since not
all transactions are settled, it doesn't make sense to ingest this data
daily. Our Payments team curates this data and officially publishes the
financials for the previous month on the first day of each month. This
is an example of a monthly dataset, one we would ingest once it becomes
available, on the 1st of each month.</p>

<p>The following figure shows this ingestion.</p>

<p><img src="https://vladris.com/blog/2021/03/12/fig3.png" alt="image"/></p>

<p><em>Sales data gets copied from the Payments team's Azure SQL to our Azure
Data Explorer cluster on a monthly cadence.</em></p>

<p>This is very similar to our previous Azure Data Factory ingestion of
page view logs, the difference being the data source - in this case we
ingest data from Azure SQL, and the ingestion cadence - monthly instead
of daily.</p>

<p>Let's define the cadence of when a dataset is ready for ingestion as
its <em>grain</em>.</p>

<blockquote>
<p>The <strong>grain</strong> of a dataset specifies the frequency at which new data
is ready for consumption. This can be continuous for streaming data,
hourly, daily, weekly, and so on.</p>
</blockquote>

<p>We would ingest a dataset with a weekly grain on a weekly cadence. The
grain is usually defined by the upstream team producing the dataset.
Partial data might be available earlier, but the upstream team can
usually tell us when the dataset is complete and ready to be ingested.</p>

<p>While some data, like the logs in our example, can be ready in real time
or at a daily grain, there are datasets who get updated once a year. For
example, businesses use fiscal years for financial reporting, budgeting
and so on. These datasets only change year over year.</p>

<p>Another ingestion parameter is the type of data load.</p>

<h2>Load type</h2>

<p>Outside of streaming data, where data gets ingested as it is produced,
we have two options for updating a dataset in our system. We can perform
a full load or an incremental load.</p>

<blockquote>
<p>A <strong>full load</strong> means we fully refresh the dataset, discarding our
current version and replacing it with a new version of the data.</p>
</blockquote>

<p>For example, our Customer Success team has the list of active customer
issues. As these issues get resolved and new issues appear, we perform a
full load whenever we ingest the active issues into our system.</p>

<p>The usual pattern is to ingest the updated data into a staging table,
then swap it with the destination table, as show in the following
figure.</p>

<p><img src="https://vladris.com/blog/2021/03/12/fig4.png" alt="image"/></p>

<p><em>Queries are running against the ActiveIssues table. We ingest the data
into the ActiveIssuesStaging table. Queries are still running against
the old ActiveIssues table. We swap the two tables. Queries already
started before the swap will run against the old tables, queries started
after the swap will run against the new table. Finally, we can drop the
old table.</em></p>

<p>Most storage solutions offer some transactional guarantees on renames to
support scenarios like this. This means if someone is running a query
against the <code>ActiveIssues</code> table, there is no chance of the query
failing due to the table not being found or of the query getting rows
from both the old and the new table. Queries running in parallel with a
rename are guaranteed to either hit the old or the new table.</p>

<p>The other type of data load is incremental.</p>

<blockquote>
<p>An <strong>incremental load</strong> means we append data to the dataset. We start
with the current version and enhance it with additional data.</p>
</blockquote>

<p>Let's take as an example a <code>PageViews</code> table. Since the Website team
only keeps logs around for 30 days and we want to maintain a longer
record when we ingest the data into our system, we can't fully refresh
the <code>PageViews</code> table. Instead, every night we take the page view logs
of the previous day and we <em>append</em> them to the table.</p>

<p>One challenge of incremental loads is to figure out exactly what data is
missing (that we need to append), and what data we already have. We
don't want to append again data we already have, as it would create
duplicates.</p>

<p>There are a couple of ways we can go about determining the delta between
upstream and our storage. The simplest one is contractual: the upstream
team guarantees that data will be <q>ready</q> at a certain time or date.
For example, the Payments team promises that the sales data for the
previous month will be ready on the 1st, by noon. In that case, on July
1st we will load all sales data with a timestamp within June and append
it to the existing sales data we have in our system. In this case, the
delta is June sales.</p>

<p>Another way to determine the delta is to keep track on our side of what
is the last row we ingested and only ingest from upstream data after
this row. This is also known as a <em>watermark</em>. Whatever is <q>under the
watermark</q> is data we already have in our system. Upstream can have
data <q>above the watermark</q>, which we need to ingest.</p>

<p>Depending on the dataset, keeping track of the watermark can be very
simple or very complex. In the simplest case, if the data has a column
where values always increase, we can simply see what the latest value is
in our dataset and ask upstream for data with values greater than our
latest.</p>

<p>We can then ask for page views with a timestamp greater than the
watermark when we append data in our system.</p>

<p>Other examples of ever-increasing values are auto-incrementing columns,
like the ones we can define in SQL.</p>

<p>Things get more complicated if there is no easy ordering of the data
from which we can determine our watermark. In that case, the upstream
system needs to keep track of what data it already gave us, and hand us
a watermark object. When we hand back the object, upstream can determine
what is the delta we need. Fortunately, this scenario is less common in
the big data world. We usually have simpler ways to determine delta,
like timestamps and auto-incrementing IDs.</p>

<p>What happens though when a data issue makes its way into the system? We
got the sales data from our Payments team on July 1st, but the next day
we get notified that there was an issue: somehow a batch of transactions
was missing. They fixed the dataset upstream, but we already loaded the
erroneous data into our platform. Let's talk about restatements and
reloads.</p>

<h2>Restatements and reloads</h2>

<p>In a big data system, it is inevitable that at some point, some data
gets corrupted, or is incomplete. The owners of the data fix the
problem, then issue a <em>restatement</em>.</p>

<blockquote>
<p>A <strong>restatement</strong> of a dataset is a revision and re-release of a
dataset after one or more issues were identified and fixed.</p>
</blockquote>

<p>Once data is restated, we need to reload it into our data platform. This
is obviously much simpler if we perform a full load for the dataset. In
that case, we simply discard the corrupted data we previously loaded and
replace it with the restated data.</p>

<p>Things get more complicated if we load this dataset incrementally. In
that case, we need to drop only the corrupted slice of the data and
reload that from upstream. Let's see how we can do this in Azure Data
Explorer .</p>

<p>Azure Data Explorer stores data in <em>extents</em>. An extent is a shard of
the data, a piece of a table which contains some of its rows. Extents
are immutable - once written, they are never modified. Whenever we
ingest data, one or more extents are created. Periodically, Azure Data
Explorer merges extents to improve query performance. This is handled by
the engine in the background.</p>

<p>The following figure shows how extents are created during ingestion,
then merged by Azure Data Explorer.</p>

<p><img src="https://vladris.com/blog/2021/03/12/fig5.png" alt="image"/></p>

<p><em>Extents are created during ingestion, then merged by Azure Data
Explorer to improve query performance</em></p>

<p>While we can't modify an extent, we can drop it. Dropping an extent
removes all data stored within. Extents support tagging, which enable us
to attach metadata to them. A best practice is to add the <code>drop-by</code> tag
to extents on creation. This tag has special meaning for Azure Data
Explorer: it will only merge extents with the same <code>drop-by</code> tag. This
will ensure that all data ingested into an extent with a <code>drop-by</code> tag
is never grouped with data ingested with another <code>drop-by</code> tag.</p>

<p>The following figure shows how we can use this tag to ensure data
doesn't get mixed, then we can drop extents with that tag to remove
corrupted data.</p>

<p><img src="https://vladris.com/blog/2021/03/12/fig6.png" alt="image"/></p>

<p><em>We ingested 2 extents with drop-by tag 2020-06-29 and 2 extents with
drop-by tag 2020-06-30. They get merged into 1 extent with drop-by tag
2020-06-29 and 1 extent with drop-by tag 2020-06-30. We can ask Azure
Data Explorer to drop all extents tagged with 2020-06-29 to remove a
part of the data.</em></p>

<p>The <code>drop-by</code> tag ensures that extents with different values for the tag
never get merged together, so we don't risk dropping more data than
what we want dropped. The value of the tag is arbitrary, we can use
anything, but a good practice is to use an ingestion timestamp. So for
example when we load data on 2020-06-29, we use the <code>drop-by:2020-06-29</code>
tag.</p>

<p>If we later learn that the data we loaded was corrupted and upstream
restates the data, we can drop the extents containing corrupted data and
re-ingest from upstream to repair our dataset.</p>

<p>Obviously, this process is more complicated than if we were doing a full
load of the data every time. In general, if we can afford a full load,
we should use that. Maintenance-wise, it is a much simpler approach.
Sometimes though, this is impossible - for example if we want to
maintain page view logs beyond the 30-day retention period upstream has,
we can't keep reloading the data. Other times, full load is just too
expensive: we end up moving the same gigabytes of data again and again,
with minor differences. For these situations, we have to look at an
incremental load and manage the additional complexity.</p>

<h2>Summary</h2>

<ul>
<li>We can ingest data continuously (streaming), or at a certain regular
cadence like daily, weekly, monthly, or yearly.</li>
<li>When we ingest data, we can perform either a full load, or we can
perform an incremental load.</li>
<li>A full load means we fully refresh the dataset, discarding our
current version and replacing it with a new version of the data.</li>
<li>An incremental load means we append data to the dataset. We start
with the current version and enhance it with additional data.</li>
<li>It is inevitable for some data to get corrupted. Once repaired
upstream, we need a way to discard the corrupted data from our
system and reload the updated data.</li>
</ul>
]]></description>
      <pubDate>Fri, 12 Mar 2021 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/12/29/recommendations.html</link>
      <guid>https://vladris.com/blog/2020/12/29/recommendations.html</guid>
      <title><![CDATA[Recommendations]]></title>
      <description><![CDATA[<h1>Recommendations</h1>

<p>I sometimes get asked for learning resources and areas aspiring software
engineers should focus on. This post will cover some of my
recommendations. This is purely for software development, design, and
engineering. I will share a complementary list of resources on soft
skills, systems, leadership, and working within organizations in a
future post.</p>

<h2>Fundamentals</h2>

<p><strong>Data structures and algorithms</strong> -- This is CS 101. Understand lists,
stacks, queues, heaps, trees, graphs, and algorithms to sort, select,
traverse etc. Understand big-O notation and complexity -- this is
important in practice, when implementing solutions that deal with
real-world data. This is foundational to the field of computer science,
so unless you are working on some cutting-edge stuff, there's probably
a well-known solution to your problem. You don't need to know all
implementations by heart but know what applies and where to look it up
when needed, be it an A* search or B-tree.</p>

<p><strong>Understand your compute target</strong> -- this can be a physical machine, an
operating system, a virtual machine like the JVM or .NET CLR, the
browser, or the cloud. Either way you need to know what resources are
available, how they are allocated, what are the performance
characteristics and so on. Without understanding your compute target you
won't be able to leverage it to its full capabilities and run the risk
of misusing it.</p>

<p><strong>Concurrent programming</strong> -- today, I believe this is unescapable.
Concurrency is everywhere, regardless of whether you are building
services that talk to each other, a multi-threaded native application,
or a Node.JS, event loop-based application. Having a good mental model
of how concurrency works, understanding deadlocks, livelocks,
synchronization mechanisms, and consistency models is foundational.</p>

<h2>Programming languages</h2>

<p>Programming languages are not just how we talk to computers, they are
tools for thought. They enable us to express solutions to problems. We
model our solutions using the languages, and different languages are
best suited to different problems. I'm a firm believer in
multi-paradigm and using the best tool for a job. Saying that
<em>everything is an object</em>, or <em>everything is a function</em> is an
oversimplification. Many modern programming languages support multiple
paradigms, so we can write object-oriented code when appropriate, and
functional code when appropriate. With that said, I suggest learning:</p>

<p><strong>A system programming language</strong> like C++, Rust or Swift if you need to
write native, performant code. These languages are close to the machine
and will help you understand OS resource management, how code gets
executed, and what impacts performance.</p>

<p><strong>A <q>higher-level</q> language</strong> for writing tools and services.
Something like C#, Java or Go. These are all garbage collected and trade
off some performance for productivity.</p>

<p><strong>A dynamic language</strong> for quick prototyping and experimentation. Python
and Ruby come to mind. While static typing is much safer for production
code, I do love <em>thinking</em> in Python.</p>

<p><strong>A purely functional language</strong> like Haskell or Idris. This is again to
understand different ways of thinking about problems. Even if you don't
get to write production code in a purely functional language, you will
learn alternative approaches to designing your code which you will be
able to apply even when using other languages.</p>

<p><strong>A language with strong support for generics</strong>, like C++, Rust, or
TypeScript. Generics are a powerful way to reuse and combine code and
understanding them will make you a better programmer.</p>

<p>From my personal experience, within the same paradigm, languages are
more similar than different. In other words, once you know two, it is
significantly easier to understand the third. There is value in learning
new programming languages to see how they differ from existing ones and
what they bring to the table.</p>

<h2>Practice</h2>

<p>Write code. Learning needs to be a mix of theory and practice. Here are
some practice ideas:</p>

<p><a href="https://en.wikipedia.org/wiki/Kata_(programming)">Code katas</a> -- These
could be some good first projects when picking up a new language. For
example: <a href="http://codekata.com/">http://codekata.com/</a>,
<a href="https://github.com/gamontal/awesome-katas">https://github.com/gamontal/awesome-katas</a>.</p>

<p><strong>Programming puzzles</strong> -- These are good ways to practice problem
solving, data structures, and algorithms. I really enjoy <a href="https://adventofcode.com/">Advent of
Code</a>, which has been running every December
since 2015. <a href="https://www.facebook.com/codingcompetitions/hacker-cup/">Facebook Hacker
Cup</a> also has
some great puzzles.</p>

<p><strong>Contribute to an open-source project</strong>, many have supportive
communities and paths to get you started.</p>

<p><strong>Work on your own project</strong>, be it a website or a game or something
else you are passionate about. Scope it to fit the amount of time you
must dedicate and use the technologies you want to learn.</p>

<p>Of course, you will do most of the <strong>learning on the job</strong>. Work on
projects that interest you, projects you can learn from, and projects
where you can apply what you learned.</p>

<h2>Books</h2>

<p>This is a list of books on software design and craftsmanship that I
highly recommend:</p>

<p><a href="https://www.goodreads.com/book/show/4845.Code_Complete">Code Complete</a>
-I love this one. This is The Big Book of Software Engineering, and it
covers the fundamentals, like writing proper functions, using good
naming in the code, testing, debugging etc.</p>

<p><a href="https://www.goodreads.com/book/show/4099.The_Pragmatic_Programmer">The Pragmatic
Programmer</a> -
Great book which gives general advice on what it takes to become a good
programmer. From basic tips like know thy text editor and use source
control to implementation and design advice.</p>

<p><a href="https://www.goodreads.com/book/show/84983.Agile_Principles_Patterns_and_Practices_in_C_">Agile Principles, Patterns and Practices in
C#</a> -
On writing software in an agile world. Principles to keep in mind (like
the Open/Close Principle, the Single Responsibility Principle etc.),
patterns to enable them, and agile practices. Also covers TDD, extreme
programming, and all the other agile methodologies.</p>

<p><a href="https://www.goodreads.com/book/show/85009.Design_Patterns">Design
Patterns</a> -
The classic book on design patterns. It is a bit cumbersome but
definitely worth reading. Patterns are basically well-known solutions to
recurring design problems. Do read <a href="https://vladris.com/blog/2020/12/10/notes-on-design-patterns.html">my previous
post</a>
and don't over-index on patterns.</p>

<p><a href="https://www.goodreads.com/book/show/44936.Refactoring">Refactoring</a> -
The classical book on refactoring code - re-structuring implementation
without changing functionality. Talks about code smells (pieces of code
that feel wrong) and how to rearchitect such code to make it right.</p>

<p><a href="https://www.goodreads.com/book/show/3139913-emergent-design">Emergent
Design</a> -
This book talks about how design emerges as code evolves. By respecting
a few principles and knowing about design patterns, you don't have to
over-design and future-proof, rather keep refactoring and extending as
new requirements come in.</p>

<p>There are a few other books which I really enjoyed, though they are a
bit different than the above. I recommend these more for the aesthetics
and insights (more on that below): <a href="https://www.goodreads.com/book/show/52084.Programming_Pearls">Programming
Pearls</a>,
<a href="https://www.goodreads.com/book/show/23498372-from-mathematics-to-generic-programming">From Mathematics to Generic
Programming</a>,
<a href="https://www.goodreads.com/book/show/405790.Beautiful_Code">Beautiful
Code</a>.</p>

<h2>Other considerations</h2>

<p><strong>Develop a sense of aesthetics</strong> - This comes with practice. Know what
good code looks like, what makes it beautiful. Don't just get code
working, try to make it beautiful.</p>

<p><strong>Understand your problem space</strong> -- Whatever you are working on,
knowing the business domain will help inform your software design.
Understand why you are doing what you are doing. Is there a better way
to solve the same business problem? Do you know what will likely come up
in 6 months from now or a year?</p>

<p><strong>Security</strong> -- Software security is critical in today's connected
world. You should understand security best practices, which hashing
algorithms to use, how to properly store secrets and passwords, how
trust gets established, attack vectors, how to create a <a href="https://en.wikipedia.org/wiki/Threat_model">threat
model</a> and so on.</p>

<p><strong>AI</strong> - AI is permeating more areas of software. It is also being
commoditized through libraries like scikit-learn and services like Azure
Cognitive Services. While I won't quite yet put it under
<em>fundamentals</em>, I believe using AI will soon be a must-know, much like
concurrent programming. Having a good understanding of the types of
problems AI can help with, when and how to apply it is very valuable.</p>

<p><strong>Keep learning</strong> -- The way we build software keeps evolving. Try to
keep up to date with recent developments and trends. This is one of the
reasons software engineering is such an exciting field: there's always
something new, there's always more to learn.</p>
]]></description>
      <pubDate>Tue, 29 Dec 2020 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/12/10/notes-on-design-patterns.html</link>
      <guid>https://vladris.com/blog/2020/12/10/notes-on-design-patterns.html</guid>
      <title><![CDATA[Notes on Design Patterns]]></title>
      <description><![CDATA[<h1>Notes on Design Patterns</h1>

<blockquote>
<p><em>Patterns mean <q>I have run out of language.</q></em> --- Rich Hickey.</p>
</blockquote>

<p>Many junior developers want to improve their software design skills by
studying design patterns. I was there too, of course. I believe there is
a big misconception of what design patterns <em>are</em>, and I believe we are,
indeed, over-indexing on them when we are thinking of software design.</p>

<p>It is very easy to over-design things, and if blindly apply design
patterns, we end up with code like the <a href="https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpriseEdition">FizzBuzz Enterprise
Edition</a>,
which in real life translate into incomprehensible software that burns
hundreds of developer-hours for even tiny changes.</p>

<h2>A good design by any other name...</h2>

<p>So what are design patterns? A common definition is:</p>

<blockquote>
<p>A software design pattern is a general, reusable solution to a
commonly occurring problem within a given context in software design.</p>
</blockquote>

<p>A lot of design patterns criticism centers around how, using some
non-object oriented language, you can express design patterns from the
Gang of Four succinctly within the language syntax, without having to
code extra scaffolding. This is why I believe there is a misconception
around what design patterns really are. My take on design patterns is
that they provide good solutions to software design problems, for
dimensions like encapsulation, decoupling etc. These patterns are
<strong>not</strong> their representation in any particular language.</p>

<p>In some instances, a language can express the same idea more succinctly.
That doesn't mean the pattern is useless. We are still modeling complex
domains with code, and we still need to account for all aspects of good
design so we don't end up with a jumbled mess. In other words, you can
write bad code in any programming language.</p>

<p>This is a recurring topic in my book <a href="https://www.manning.com/books/programming-with-types">Programming with
Types</a>, where I
show alternative implementations to the strategy pattern, the decorator
pattern, and the visitor pattern. The first two have more succinct
functional implementations, while the last one can be better
encapsulated using a discriminated union type. Regardless of how we
express the design, we are still solving the same problem. Which is why
I believe over-indexing on learning design patterns as code recipes is a
mistake.</p>

<h2>Smelling software rot</h2>

<p>As a young developer wanting to learn design patterns, I stumbled upon
the <a href="https://www.goodreads.com/book/show/84983.Agile_Principles_Patterns_and_Practices_in_C_">Agile Principles, Patterns, and Practices in
C#</a>
book, probably because it contained <q>patterns</q> in the title. But this
book is a real gem on good design, and I highly recommend it.</p>

<p>Chapter 7 talks about design smells. Design smells are a sign that the
software is rotting and might need refactoring. Here are a few examples
from the book:</p>

<ul>
<li><strong>Rigidity</strong> - because of poorly-structured dependencies, a small
change in one part of the code causes a cascade of subsequent
changes in other parts of the code.</li>
<li><strong>Viscosity</strong> - when modifying the code, it is easier to add a hack
rather than to implement a desing-preserving change. In other words,
it is easier to do the wrong thing than it is to do the right thing.</li>
<li><strong>Needles Repetition</strong> - copy/pasted code, often with minor
modifications, which makes minor updates very difficult to apply
across the code base.</li>
</ul>

<p>There are a bunch more in the book and plenty more documented online.</p>

<p>Developing a nose for design is, in my opinion, a lot more important
than <em>knowing</em> patterns. And while you can read about common smells,
nothing beats experience (much like reading descriptions of actual
smells vs. using your nose).</p>

<p>When I write code, sketching out a solution to some problem, I refactor
it several times before I submit a pull request. It is an iterative
process - I try something out, notice something off with the design,
refactor to improve and simplify.</p>

<p>Instead of bringing a set of prefabricated solutions and checking to see
which one fits the problem best, we can focus on refactoring smells
away. This avoids the FizzBuzz Enterprise Edition problem. The
Enterprise Edition of FizzBuzz is full of patterns! But it is needlessly
complex. Accidental complexity is one of the worst smells. I mentioned
accidental complexity in the <a href="https://vladris.com/blog/2020/01/19/time-and-complexity.html">Time and
Complexity</a>
post and I will probably write more about it since I find this a
fascinating topic.</p>

<p>Smells tell us how a design is bad, but what makes a good design?</p>

<h2>SOLID principles and beyond</h2>

<p>There is a small set of design principles, known as the SOLID design
principles which make for good code:</p>

<ul>
<li><strong>The single-responsibility principle</strong> - a class (or program unit)
should be responsible for one thing, and have to change only when
the requirements of that thing change.</li>
<li><strong>The open/closed principle</strong> - code should be open for extension,
closed for modification.</li>
<li><strong>The Liskov substitution principle</strong> - replacing an instance of
some type with an instance of a subtype should maintain program
correctness.</li>
<li><strong>The interface segregation principle</strong> - single-responsibility
principle applied to interfaces.</li>
<li><strong>The dependency-inversion principle</strong> - code should depend on
abstractions, not concrete implementations.</li>
</ul>

<p>While a lot of the literature is centered around object-oriented
programming, these principles transcend OOP. For example, an interface
can be an <code>interface</code> definition, a function signature, a set of APIs
exposed by a module etc. Similarly, subtyping does not imply
inheritance - check out my
<a href="https://vladris.com/blog/2019/12/27/variance.html">Variance</a> post which
covers this in more depth.</p>

<p>These SOLID principles are the subject of chapter 8 through 12 of the
<em>Agile Principles, Patterns, and Practices in C# book</em>.</p>

<p>Knowing these principles and having a nose for design smells, you can
derive any design pattern from first principles. In some cases it's
easier if you are aware of the pattern - you don't have to spend time
solving an already-solved problem. But it doesn't work the other way
around: You can't start with a set of patterns without understanding
the underlying principles and without being able to tell when a design
smells.</p>

<p>Beyond these principles, exploring well-crafted software helps us
develop a sense of good design. In the real-world, most codebases have
good and bad parts. I won't go into the details of why in this article,
but keep this in mind when working on your project. Which parts are
designed well? Why? Which parts could benefit from a refactoring? Why?</p>

<p>Learning design patterns is secondary to understanding good and bad
design.</p>
]]></description>
      <pubDate>Thu, 10 Dec 2020 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/11/27/changing-data-classification-through-processing.html</link>
      <guid>https://vladris.com/blog/2020/11/27/changing-data-classification-through-processing.html</guid>
      <title><![CDATA[Changing Data Classification Through Processing]]></title>
      <description><![CDATA[<h1>Changing Data Classification Through Processing</h1>

<p>This is an excerpt from a draft of chapter 10 of my book, <a href="https://www.manning.com/books/azure-data-engineering">Azure Data
Engineering</a>,
which deals with compliance. In this article we'll look at a few
techniques to transform sensitive user data into less sensitive data. In
the book, this includes code samples for implementation on Azure Data
Explorer, which are omitted from this article. Let's start with a
couple of definitions.</p>

<h2>User Data</h2>

<p>User data is data that can be directly tied to the user. This class of
data is important since this is what GDPR covers. User data also comes
in a couple of subcategories. One of them is <em>End User Identifiable
Information</em> or <em>EUII</em>.</p>

<blockquote>
<p><strong>End user identifiable information</strong> is information that can directly
identify the user. Examples of EUII are name, email address, IP
address, or location information.</p>
</blockquote>

<p>As data moves through our systems, we generate various IDs. Any data
that we have tied to such an ID, for example order history for account
ID, is called <em>End User Pseudonymous Information</em> or <em>EUPI</em>.</p>

<blockquote>
<p><strong>End user pseudonymous information</strong> are IDs used by our systems
which, in conjunction with additional information (for example a
mapping table) can be used to identify the user.</p>
</blockquote>

<p>Note the important distinction: When we look at EUII, for example name
and address, we can immediately identify the user. When we look at EUPI,
for example account ID, we need an additional mapping to tell us which
user the account ID belongs to.</p>

<p>In general, we have one primary ID (or several) which directly
identifies the user, which we consider EUII, and multiple other IDs
which indirectly identify the user through their connection to the
primary ID. These other IDs are EUPI.</p>

<h2>Changing Classification Through Processing</h2>

<p>In general, we restrict the number of people who can access sensitive
data. In most cases, access is <em>on a need-to-know basis</em>, where data
scientists and engineers allowed to process this data have done some
compliance training and understand the risks and liabilities.</p>

<p>In some scenarios we want to process data so that it becomes less
sensitive. A good example is we want to open it up for more data
scientists to look at. In this article we will look at a few techniques
for achieving this.</p>

<p>Let's start by defining two datasets, as shown in the following figure:</p>

<p><img src="https://vladris.com/blog/2020/11/27/fig1.png" alt="image"/></p>

<p>The first dataset, <em>User profiles</em>, contains user accounts, including
names, credit cards, and billing addresses. We omitted actual billing
addresses to keep things short. This dataset also contains a <em>User ID</em>
column which associates an identification number with each user. This is
the primary ID in our system, since we can use it to link back to a
user's profile information.</p>

<p>The second dataset, <em>User telemetry</em>, contains telemetry data we collect
from our users. It contains the user ID, timestamp and product feature
the user engaged with.</p>

<p>Let's see some techniques we can use on the <em>User telemetry</em> table to
change its classification to something less sensitive.</p>

<h3>Aggregation</h3>

<p>The first technique is aggregation: we can take user identifiable
information from multiple users, aggregate it, and get rid of the end
user identifiable part. For example, if we collect telemetry from our
users that captures which features of our product they are using, we can
aggregate it, so we know how much each feature is being used, but not
who used what.</p>

<p>The following figure shows how aggregation transform user identifiable
information into data that can't be tied back to individual users.</p>

<p><img src="https://vladris.com/blog/2020/11/27/fig2.png" alt="image"/></p>

<p>Before processing, we could see exactly what set of features an
individual user was using, which has privacy implications. After
aggregation, we can no longer tell that. We still have valuable data --
we know which features of our product are the most used, which ones are
not that important to our customers etc. We can store this data for
analytics and ML purposes without having to worry about end user
privacy.</p>

<blockquote>
<p>Data <strong>aggregation</strong> is the processing of data into a summarized
format. This can be used to transform the data so it can no longer be
tied to individual users.</p>
</blockquote>

<p>But maybe we want to know more: we want to see when each feature is used
or how our customers use different features in conjunction. Now simply
counting feature usage is not enough. We can use a different technique
for that: anonymization.</p>

<h3>Anonymization</h3>

<p>We can use anonymization to unlink the data from the end user. Once the
data is no longer connected to a user identifier, we can't tell which
user it came from. Going back to our telemetry example, if we want to
know when features are used, but don't care who uses them, we can get
rid of the user identifier. The following figure shows how we can
anonymize data by dropping the user identifiers.</p>

<p><img src="https://vladris.com/blog/2020/11/27/fig3.png" alt="image"/></p>

<p>Maybe this is not enough either. What if we still need to see which
features are used together by a user, but we don't really care who the
user is? We can still anonymize by replacing user identifiers (which can
be tracked back to the user) with randomly generated IDs. The following
figure shows how we can anonymize the data by replacing each user ID
with a randomly generated GUID.</p>

<p><img src="https://vladris.com/blog/2020/11/27/fig4.png" alt="image"/></p>

<p>Note that we are intentionally not persisting a mapping between user IDs
and corresponding random IDs. We generate the random IDs once and
intentionally <q>forget</q> the association.</p>

<p>Once this happens, we can no longer tie the data back to the user, so it
is no longer user identifiable. We can still tie together datasets by
the random ID, but there is no way to associate the random ID with a
user.</p>

<blockquote>
<p><strong>Anonymization</strong> is the process of removing user identifiable
information from the data or replacing it with data that cannot be
linked back to a user.</p>
</blockquote>

<p>If we get new telemetry from our users, we won't be able to generate
the same GUID when anonymizing. Each time we run the query we will get
different random IDs corresponding to our users. In some cases, this
might not be enough. Or we might need to maintain that ability to link
back to our original user IDs but restrict who can make that
association. For these cases, we can use pseudonymization.</p>

<h3>Pseudonymization</h3>

<p>In this case, we have scenarios for which we still need to know who the
data belongs to, but this is not needed for all scenarios. For example,
we might want to keep track of which user used which features so we can
notify them of updates to that feature. But for other analytics, it is
irrelevant who the user is. For the first case, we have a small set of
people who can view this association. For analytics, we have a large
team of people looking at the data, but from their perspective, it is
anonymous.</p>

<p>We can achieve this by pseudonymizing the data. The difference between
pseudonymization and anonymization is that pseudonymization gives us a
way to reconstruct the relationship.</p>

<p>When we looked at anonymizing data, we swapped out the user ID with a
randomly generated ID. Unless we explicitly stored which user ID got
assigned which random ID, we can no longer recover the link.</p>

<p>For pseudonymization, we replace random IDs with something more
deterministic. This can be either a hash of the user ID, or an
encryption of the user ID.</p>

<p>As a reminder, hashing is a one-way function. Give the result of a hash,
you cannot <q>un-hash</q> it to get the original value. Encryption is
different -- an encrypted value can be decrypted if we know the
encryption key.</p>

<blockquote>
<p><strong>Pseudonymization</strong> is the process of replacing user identifiable
information with a pseudonym. The data can be linked back to a user
given some additional information.</p>
</blockquote>

<p>Let's look at both approaches.</p>

<h4>Pseudonymizing by hashing</h4>

<p>If we hash the user IDs and provide a dataset with just hashes, the only
way to tie this pseudonymous data back to actual users would be to take
all the user IDs in our system and hash them to see where we find a
match.</p>

<p>If we restrict the access to the user IDs, then someone who can only
query the pseudonymized table can still see all the connections within
the dataset (which features are used by which user), but instead of
seeing a user ID, they see a pseudonymous identifier. The following
figure shows the transformation.</p>

<p><img src="https://vladris.com/blog/2020/11/27/fig5.png" alt="image"/></p>

<p>Note that if we only have this dataset consisting of <em>Pseudonymous ID</em>,
<em>Timestamp</em>, and <em>Feature</em>, we can't produce a user ID. On the other
hand, if we have a user ID, we can always hash it and link it to the
pseudonymized data.</p>

<p>We can use this technique in cases when the data scientists processing
the pseudonymized data don't have access to the unprocessed, end user
identifiable data. This way, they get a dataset that is, for all intents
and purposes, just like the original, except there is no mention of user
IDs.</p>

<p>This doesn't work if the user IDs are also visible since it is easy to
hash them again and produced the pseudonymous IDs. One option is to keep
the hashing algorithm secret and add a salt. In cryptography, a salt is
some additional secret data mixed-in, to make it harder to recreate the
connection. For example we can XOR the user ID with some number (our
salt).</p>

<p>Now, as long as the salt is kept secret, someone can't get from user ID
to the pseudonymous ID even if they know which hashing algorithm is used
for pseudonymization.</p>

<p>Let's now look at the alternative to hashing: encryption.</p>

<h4>Pseudonymizing by encrypting</h4>

<p>If we encrypt the user IDs and provide a dataset with encrypted values,
the only way to tie this back to actual users would be to decrypt. As
long as the encryption key is secure and only available on a
need-to-know basis, people that don't need to know can't recover the
association.</p>

<p>This is similar to the hashing technique we just saw, except it is a
two-way transformation. Even without having access to a user ID to hash,
we can produce a user ID by decrypting an encrypted pseudonymized ID.
Figure 6 shows how this would look like.</p>

<p><img src="https://vladris.com/blog/2020/11/27/fig6.png" alt="image"/></p>

<p>We will use encryption instead of hashing if we have a scenario in which
we don't have the original dataset available, but we need a way to
recover it. In this case, we can rely on the two-way transformation
provided by encryption and restore the original dataset by decrypting
the pseudonymized dataset.</p>

<p>An alternative to transforming data is masking.</p>

<h3>Masking</h3>

<p>Masking means hiding parts of the data from whoever access it, even if
the data is fully available in our system. Think of how social security
numbers are reduced to the last 4 digits: <code>***-**-1234</code>.</p>

<p>Masking sensitive data makes it less sensitive -- obviously, even with
bad intent, someone can't do much with just the last 4 digits of a
social security number, with just the city and state of a home address,
or with the first few digits of a phone number.</p>

<p>Masking the data does require an additional layer in between the raw
storage and people querying the data, which determines who gets to see
the unmasked, full dataset, and who is restricted to a more limited view
of the data. The following figure shows how masking looks like for our
<em>User profile</em> table.</p>

<p><img src="https://vladris.com/blog/2020/11/27/fig7.png" alt="image"/></p>

<p>Unlike our previous techniques, which transformed the data, this happens
in-place. We still have the full credit card number stored, but not
everyone querying the table will be able to see it.</p>

<blockquote>
<p><strong>Masking</strong> leverages an additional layer between the raw data and
query issuers to hide sensitive information from non-privileged
access.</p>
</blockquote>

<p>The good news is many storage solutions and database engines offer such
a layer out-of-the-box (see Azure Data Explorer's <a href="https://docs.microsoft.com/en-us/azure/data-explorer/kusto/management/rowlevelsecuritypolicy">row level
security</a>
for example).</p>

<h2>Summary</h2>

<p>In this article we looked at a few ways in which we can take sensitive
data and make it less sensitive:</p>

<ul>
<li>Aggregating data makes it impossible to connect it back to
individual users.</li>
<li>Anonymizing data, while a bit more involved than aggregating,
preserves the granularity of user-level data, while removing the
identifiable parts.</li>
<li>In some cases, we do have legitimate scenarios in which we want to
trace back the data to actual users. In this case, we can use
pseudonymization to make the data partially anonymous and only
restore the link with the real user ID on a need-to-know basis.</li>
<li>Hashing is a one-way transformation of the data. Given a
pseudonymized ID, we can't recover a user ID. We can restore the
association by hashing user ID again and joining on the
pseudonymized ID. Adding secret salt to a hash makes it harder to
restore the association (one would need to also know the salt
value).</li>
<li>Encryption is a two-way transformation, which requires an additional
piece of information: a key. Given a pseudonymized ID, we can
recover the user ID if we have the key by decrypting the data.</li>
<li>Masking is another technique for hiding sensitive information. In
this case, the data is not transformed, rather an in-between layer
can hide sensitive information and only make it available when
appropriate.</li>
</ul>

<p>This are important techniques to know when dealing with sensitive data,
since they all allow us to make more data available to more analytical
scenarios without compromising on user privacy.</p>
]]></description>
      <pubDate>Fri, 27 Nov 2020 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/11/13/data-quality-testing-patterns.html</link>
      <guid>https://vladris.com/blog/2020/11/13/data-quality-testing-patterns.html</guid>
      <title><![CDATA[Data Quality Testing Patterns]]></title>
      <description><![CDATA[<h1>Data Quality Testing Patterns</h1>

<p>The insights generated by a data platform are only as good as the
quality of the underlying data. I briefly mentioned data quality in my
<a href="https://vladris.com/blog/2019/12/08/notes-on-data-engineering.html">Notes on Data
Engineering</a>
blog post and elaborated on the DataCop solution in the <a href="https://medium.com/data-science-at-microsoft/partnering-for-data-quality-dc9123557f8b">Partnering for
data
quality</a>
Medium article I co-authored with my colleagues.</p>

<p>In this post I want to talk about some of the requirements and common
patterns of data quality test solutions. I maintain that in the future
data quality testing will be commoditized and offered <q>as a service</q>
by cloud providers. As of today, it is still something we have to stitch
together or onboard a 3rd party solution. Below is a blueprint for such
solutions.</p>

<h2>Data Fabrics</h2>

<p>Any data quality test run is eventually translated into a query
executing on the underlying data fabric. In Azure, this can be, for
example, Azure SQL, Azure Data Explorer, Data Lake Storage etc. Data
quality frameworks need to support multiple data fabrics for several
reasons. First, in a big enough enterprise, data will live in multiple
systems. Second, different data fabrics are optimized for different
workloads, so even if we are very strict about the number of technology
choices, sometimes it simply makes sense to leverage different data
fabrics for different workloads.</p>

<p>We probably don't want to manage multiple data quality solutions
specializing in different data fabrics, since data quality solutions
become part of our infrastructure. Regardless of target data fabrics,
any data quality solution needs to implement some form of test
scheduling, alerting etc.</p>

<p>The best pattern is to support multiple data fabrics through a plug-in
model, so support for additional data fabrics can be easily added by
implementing a new plug-in, while the core of the system is shared for
all data fabrics plugged into the system.</p>

<h2>Types of Tests</h2>

<p>The <a href="https://smartbridge.com/data-done-right-6-dimensions-of-data-quality/">6 Dimensions of Data
Quality</a>
article talks about <em>completeness</em>, <em>consistency</em>, <em>conformity</em>,
<em>accuracy</em>, <em>integrity</em>, and <em>timeliness</em>. I think of data quality
testing like unit testing for code, so I will present a slightly
different take on this. Some of the dimensions are harder to test for
than others, for example checking consistency across multiple data
systems is non-trivial (more equivalent to an integration test). Some of
the dimensions have nuances -- for example detecting anomalies in day
over day data volume change to identify potential issues vs. just
looking at a point in time.</p>

<h3>Availability</h3>

<p>The simplest type of data test is availability, meaning <em>is data
available for a certain date</em>. If, for example, we ingest yesterday's
telemetry data every night, we expect to have yesterday's telemetry
data available in our system tomorrow.</p>

<p>This type of test can be implemented as a query against the underlying
data fabric that ensures some data is there. That can mean a query that
returns at least one row passes the test. This can be an early smoke
test we can run before performing more involved testing.</p>

<h3>Correctness</h3>

<p>This type of test ensures data is <em>correct</em>, based on some criteria. For
example, ensuring columns that shouldn't be empty are not empty, values
are within expected ranges, and so on.</p>

<p>This type of test can be implemented as a query against the underlying
data fabric that ensures no out-of-bounds values are returned. Going
back to the unit test equivalency, we likely want multiple correctness
tests per dataset, one or more per column we want to test.</p>

<h3>Completeness</h3>

<p>Completeness tests expand on availability tests and validate not only
that some data is available, but that <em>all</em> the data is available.</p>

<p>In some cases, this can be an exact query: for example, if we are
expecting some data for all 50 states of US, we can check that the count
of distinct states is 50.</p>

<p>More advanced checks look at historical data and ensure the volume of
the data we are checking is within a certain threshold -- for example,
our telemetry data volume should be within +/-5% of the data volume we
observed yesterday.</p>

<h3>Anomaly detection</h3>

<p>We won't go to deep into this, but there are some complexities
associated with the previous type of historical data checks. For
example, website traffic volume, depending on the website, might be very
different day over day between weekends and workdays, or during holidays
etc.</p>

<p>For these situations we can use more complex AI-based anomaly detection
to track volume over time until the system can identify anomalous data.</p>

<h2>Queries, Code or Configuration</h2>

<p>The implementation of tests can be done as queries, code, configuration,
or a mix.</p>

<p>Implementing all tests as queries means writing each test as a stored
procedure (or equivalent), so it is fully implemented on the data fabric
it executes against. The test framework just invokes the test and reads
the result. The main challenge with this is that there is not a lot of
reuse. Since the framework ends up just calling a stored procedure, it
is up to the test author to write the test, which is ultimately an
arbitrary query.</p>

<p>Implementing all tests as code means wrapping each data quality test
into a test method in some programming language. The main advantage of
this is we can use an off-the-shelf test framework with all its
benefits. Unlike data quality testing, the field of software testing is
mature. On the other hand, the main drawback is that authoring tests as
code really raises a barrier to entry, making it harder for
non-engineers to create tests.</p>

<p>Tests as configuration means defining tests using text configuration
files in a format like JSON, YAML, or XML. The framework interprets
these and translates them into the final queries to execute against the
data fabric. The main advantage of this approach is a fairly data
fabric-independent way to specify tests, around which we can build
schema validation etc. The disadvantage is increased complexity in the
framework, as it must translate configuration to queries.</p>

<p>What works best, from my experience, is a mix of queries and
configuration: give enough flexibility in the config schema to author
custom queries and let the framework handle some of the common concerns
like scheduling.</p>

<h2>Test Execution</h2>

<p>Another important concern is when we want to run a given data quality
test.</p>

<p>In some scenarios we want to run tests as part of a data movement
workflow. We want to either check that the data is in good shape at the
source, before we copy it, or check that the data is in good shape after
it got copied to the destination. Let's call this type of <em>execution on
demand</em>. This type of test execution is integrated in the ETL pipeline.</p>

<p>In other scenarios we want to run the tests on a schedule, as we expect
the data to be available. For example, if data should have arrived in
our SQL database by 7 AM every morning, we want to run our data quality
tests at 7 AM to make sure everything is in good shape. In this case, we
don't really care how the data gets here, so we are running independent
of the ETL pipeline that brings the data in. Let's call this <em>scheduled
execution</em>.</p>

<p>A good data quality test framework should support both on demand and
scheduled test execution, as there is room (and need) for both types of
tests.</p>

<h2>Monitoring and Alerting</h2>

<p>A data quality framework must be integrated with an alerting system such
that whenever a data quality test fails, data engineers are proactively
alerted so they can start investigating/mitigating the data issue.</p>

<p>A dashboard showing the overall health of the data platform is another
important component. This should include data quality for all datasets
under test, so stakeholders suspecting a data issue can quickly check to
see when did the latest tests run for a given dataset and what were the
results.</p>

<p>A slightly more advanced capability is lineage tracking -- if we
identify an issue with a dataset, do we know what is the impact? What
analytics or machine learning models or downstream processing is
impacted? Tracking metadata like lineage is a deep topic itself but
integrating this with a data quality framework enables very powerful
observability.</p>

<h2>Summary</h2>

<p>In this post we covered some patterns for data quality testing:</p>

<ul>
<li>Supporting multiple data fabrics via a plug-in model.</li>
<li>Types of tests, from simple availability to anomaly detection.</li>
<li>How to best specify tests as a mix of queries and configuration.</li>
<li>Test execution, both on a schedule and on-demand.</li>
<li>Monitoring and alerting to bubble up data quality issues.</li>
</ul>

<p>A data quality test framework is a critical part of a data platform,
giving confidence in the results produced by all workloads running on
the platform.</p>
]]></description>
      <pubDate>Fri, 13 Nov 2020 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/10/08/azure-data-engineering.html</link>
      <guid>https://vladris.com/blog/2020/10/08/azure-data-engineering.html</guid>
      <title><![CDATA[Azure Data Engineering]]></title>
      <description><![CDATA[<h1>Azure Data Engineering</h1>

<p>I am happy to announce that my new book, <a href="https://www.manning.com/books/azure-data-engineering">Azure Data
Engineering</a>,
launched in Manning Early Access Preview (MEAP). While still a work in
progress, the first chapters are available online. As I keep working on
the book and polishing the draft, more chapters will be added, and
existing chapters will be updated. That being said, the preview is now
live.</p>

<p><img src="https://vladris.com/blog/2020/10/08/book.png" alt="image"/></p>

<p>For the past few years, I had the opportunity to work as the architect
for Azure's growth team. Ron Sielinski, our director of data science,
describes how our team uses Azure to understand Azure in <a href="https://medium.com/data-science-at-microsoft/using-azure-to-understand-azure-1c8f5dc60a0a">this great
article</a>
on our <a href="https://medium.com/data-science-at-microsoft">Data Science @
Microsoft</a> Medium
publication.</p>

<p>Our engineering team maintains a big data platform, built fully on
Azure, which supports all our team's workloads. After we launched our
Medium publication, I contributed a bunch of articles describing some of
our infrastructure, challenges, and solutions. I talked about how we use
<a href="https://medium.com/data-science-at-microsoft/azure-data-explorer-at-the-azure-business-scale-89262ef8c1fd">Azure Data
Explorer</a>,
how we enabled <a href="https://medium.com/data-science-at-microsoft/how-we-built-self-serve-data-environment-tools-with-azure-3951a698fc9d">self-serve
analytics</a>,
how we scaled out our <a href="https://medium.com/data-science-at-microsoft/running-machine-learning-at-scale-808b90f0ec75?source=friends_link&amp;sk=f89feb151de7645a75fad0b84911c9a6">ML
platform</a>,
<a href="https://medium.com/data-science-at-microsoft/common-data-engineering-challenges-and-their-solution-dd51872812ac">common
challenges</a>
I noticed across the industry, and <a href="https://medium.com/data-science-at-microsoft/partnering-for-data-quality-dc9123557f8b">data
quality</a>.</p>

<p>There are plenty of resources out there covering statistics, data
science, and machine learning, but comparatively little covering the
engineering aspects of working with big data. This book is what I wish I
had available to read when joining the team, to help navigate this
complex space and lessons I had to learn the hard way.</p>

<h2>The <q>engineering</q> in data engineering</h2>

<p>While many data science projects start as exploratory, once they show
real value, they need to be supported in an ongoing, reliable fashion.
In the software engineering world, this is the equivalent of taking a
research, proof of concept, or hackathon project and graduating it into
a fully production-ready solution. While a hack or a prototype can cut
many shortcuts and focus on <q>the meat of the problem</q> it addresses, a
production-ready system does not cut any corners. This is where the
engineering part of software engineering comes into play: the
engineering rigor to build and run a reliable system. This includes a
plethora of concerns like architecture and design, performance,
security, accessibility, telemetry, debuggability, extensibility and so
on.</p>

<blockquote>
<p><strong>Data engineering</strong> is the part of data science dealing with the
practical applications of collecting and analyzing data. It aims to
bring engineering rigor to the process of building and supporting
reliable data systems.</p>
</blockquote>

<p>Data engineering is surprisingly similar to software engineering and
frustratingly different. While we can leverage a lot of the learnings
from the software engineering world, as we will see in this book, there
is a unique set of challenges we will have to address. Some of the
common themes are making sure everything is tracked in source control,
automatic deployments, monitoring and alerting. A key difference between
data and code is that code is static: once the bugs are worked out, a
piece of code is expected to consistently work reliably. On the other
hand, data moves continuously into and out of a data platform and it is
very likely for failures to occur due to various external reasons.
Governance is another major topic which is specific to data: access
control, cataloguing, privacy, and regulatory concerns are a big part of
a data platform.</p>

<p>The main theme of the book is bringing some of the lessons learned from
data engineering over the past few decades to the data space, so you can
build a data platform exhibiting the properties of a solid software
solution: scale, reliability, security, and so on.</p>

<h2>Anatomy of a big data platform</h2>

<p>A big data platform ingests data from multiple sources into a storage
layer. Data is consumed from the storage layer to enable various
workloads (data modeling, analytics, machine learning). Data is then
distributed downstream to consumers. All the activity in a data platform
needs to be orchestrated by an orchestration layer. Governance is
extremely important. And, of course, DevOps is the key: deploying
everything from source control.</p>

<p><img src="https://vladris.com/blog/2020/10/08/platform.png" alt="image"/></p>

<p>The book is divided in 3 parts, each part looking at a big data platform
through a different lens:</p>

<ul>
<li>Part 1 of the book will focus on <strong>infrastructure</strong>, the core
services of a data platform.

<ul>
<li>We will start with <strong>storage</strong>, the backbone of any data
platform. Chapter 2 will cover the requirements and common
patterns for storing data in a data platform.</li>
<li>Since our focus is on production systems, in chapter 3 we'll
discuss <strong>DevOps</strong> and what DevOps means for data.</li>
<li>Data is ingested into the system from multiple sources. Data
flows into and out of the platform and various workflows are
executed. All of this needs an orchestration layer to keep
things running. We will talk about <strong>orchestration</strong> in chapter 4.</li>
</ul></li>
<li>Part 2 will focus on the 3 main <strong>workloads</strong> that a data platform
must support:

<ul>
<li><strong>Modeling</strong>: this includes aggregating and reshaping the data,
standardizing schema, and any other processing of the raw input
data. This makes the data easier to consume by the other two
main processes: analytics and machine learning. We will talk
about data modeling in chapter 5.</li>
<li><strong>Analytics</strong>: this covers all analysis and reporting on the
data, deriving knowledge and insights. We will look at ways to
support this in production in chapter 6.</li>
<li><strong>Machine learning</strong>: these are all machine learning models
training on the data. We cover running ML at scale in chapter 7.</li>
</ul></li>
<li>Part 3, <strong>governance</strong>, is a major topic with many aspects. We will
cover governance in chapters 8, 9, and 10, touching on the key
topics:

<ul>
<li><strong>Metadata</strong>: cataloguing and inventorying the data, tracking
lineage, definitions and documentation is the subject of chapter 8.</li>
<li><strong>Data quality</strong>: how to test data and asses its quality is the
topic of chapter 9.</li>
<li><strong>Compliance</strong>: honoring complying requirements like the General
Data Protection Regulation (GDPR), handling sensitive data, and
controlling access is covered in chapter 10.</li>
<li>After all the processing steps, data eventually leaves the
platform to be consumed by other systems. We will cover the
various patterns for <strong>distributing data</strong> in chapter 11.</li>
</ul></li>
</ul>

<p>The examples in the book are built on Azure, using a specific set of
technologies, but the patterns should apply regardless of specific tech
choices or even cloud providers. Check out the book
<a href="https://www.manning.com/books/azure-data-engineering">here</a> and follow
me on <a href="linkedin.com/in/vladris/">LinkedIn</a> or
<a href="https://twitter.com/vladris">Twitter</a> for updates.</p>

<p>Also posted on
<a href="https://medium.com/@vladris/azure-data-engineering-8b5280a12048">Medium</a>.</p>
]]></description>
      <pubDate>Thu, 08 Oct 2020 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/04/27/machine-learning-at-scale.html</link>
      <guid>https://vladris.com/blog/2020/04/27/machine-learning-at-scale.html</guid>
      <title><![CDATA[Machine Learning at Scale]]></title>
      <description><![CDATA[<h1>Machine Learning at Scale</h1>

<p>This is a cross-post of the article I wrote for Data Science @
Microsoft, <a href="https://medium.com/data-science-at-microsoft/running-machine-learning-at-scale-808b90f0ec75">Running machine learning at
scale</a>.</p>

<p>Our team runs dozens of production machine learning models on a daily,
weekly, and monthly basis. We recently went through a redesign of our ML
infrastructure to increase its abilities to enable self-serve, scale to
match computing needs, reduce impacts among models running on the same
VM, and remove differences between dev and production environments. In
this post, I will describe the challenges we faced with the previous
infrastructure and how we addressed them with our Version 2
architecture.</p>

<h2>Version 1</h2>

<p>Our machine learning engineers use Python and R to implement models. Our
Version 1 infrastructure used a custom XML format from which we
generated Azure Data Factory (ADF) v1 pipelines to copy the model input
data to blob storage. Then the models ran on a set of VMs our team
maintained. The models read their input from and wrote their output back
to blob storage. The ADF pipelines then copied the outputs to <a href="https://vladris.com/blog/2020/03/01/azure-data-explorer.html">Azure
Data
Explorer</a>
and to our data distribution Data Lake.</p>

<p><img src="https://vladris.com/blog/2020/04/27/v1.png" alt="image"/></p>

<p><em>The Control VM consumes XML from Git and generates ADF pipelines to
orchestrate data movement and run ML code on a set of VMs.</em></p>

<p>The V1 infrastructure had several challenges we set out to overcome:</p>

<ul>
<li><strong>No self-serve</strong>: Much like how we <a href="https://vladris.com/blog/2020/02/01/self-serve-analytics.html">implemented a self-serve
environment for
analytics</a>,
we wanted to do something similar for machine learning, so our ML
engineers can create and deploy models without needing help from the
data engineering team.</li>
<li><strong>Auto-scaling</strong>: We have some compute-intensive models that run on
a certain day of the month when upstream datasets become available.
For a few days, we need large compute. Then, until the next month,
our compute needs decrease significantly. The V1 infrastructure
didn't account for this and we had a constant number of VMs running
at all times.</li>
<li><strong>Isolation</strong>: We used to pack multiple models on the same VM, so if
one of them consumed, for example, too much RAM, it would impact all
the other models running on the same VM. We needed better isolation.</li>
<li><strong>Differences between dev and prod environments</strong>: One issue we kept
hitting involved models that ran fine on the ML engineer's VM but
failed when moving to production because of environment differences
such as missing packages.</li>
</ul>

<p>The combination of these issues created significant operational costs
for the data engineering team: VM management, scaling issues, and having
to re-run models that failed because of either resource constraints or
bugs caused by missing packages in the production environment. As our
machine learning engineers develop more and more models, we decided to
invest in making our infrastructure more robust, scalable, and
self-serve.</p>

<h2>Version 2</h2>

<p>Our Version 2 infrastructure aims to address all these issues and
provide a scalable, self-serve platform for machine learning. Built
fully on Azure, it is made up of the following components, which we'll
discuss in turn:</p>

<ul>
<li>Orchestration.</li>
<li>Storage and distribution.</li>
<li>Compute.</li>
<li>DevOps.</li>
<li>Monitoring and alerting.</li>
</ul>

<p><img src="https://vladris.com/blog/2020/04/27/v2.png" alt="image"/></p>

<p><em>ADF pipelines deployed from Git orchestrate data movement and running
ML code, also deployed from Git, on Azure Machine Learning. Data is
distributed through ADLS. The system is monitored using Azure Monitor.</em></p>

<h3>Orchestration</h3>

<p>For orchestration, we use Azure Data Factory V2. In contrast to our V1
infrastructure, we don't use XML to generate pipelines, rather we
provide a set of
<a href="https://docs.microsoft.com/en-us/azure/data-factory/solution-templates-introduction">templates</a>
that ML engineers can use to author the pipelines themselves. We have a
dev ADF and a production one.</p>

<p>In general, an end-to-end machine learning pipeline has three steps:
Move inputs, kick off compute, and move outputs. Templates make it easy
to create and configure a pipeline.</p>

<p>We use <a href="https://docs.microsoft.com/en-us/azure/data-factory/continuous-integration-deployment">CI/CD for
ADF</a>:
The dev ADF instance is synced with Git, and so an ML engineer can
submit a pull request for review. Once approved and merged to master,
ADF generates the ARM template we use to deploy the production ADF
instance.</p>

<p>The two data factories are similar, except that they are connecting to
different environments: Dev to the development storage and compute, and
production to the production storage and compute, which is locked down.
This addresses one of the limitations of our V1, as we now have similar
dev and production environments and so graduating a model from dev to
production is much more seamless.</p>

<h3>Storage and distribution</h3>

<p>For storage, we switched from blob to Azure Data Lake Storage (ADLS)
gen2. ADLS gen2 is backed by blob storage, with a couple of important
additional features: A hierarchical file system and granular access
control. Both are key to our infrastructure.</p>

<p>The hierarchical file system allows us to create a common folder
structure for our models, with separate folders for inputs and outputs
for each run. The granular access control allows us to enforce who gets
to see what data. This is an important aspect of our platform, since
some models are trained on sensitive information such as Microsoft
revenue that not everyone can view.</p>

<p>Because we are already distributing data through ADLS, we can skip a
copy step: Instead of moving the model output to our data distribution
Data Lake, we can share it in place, applying proper access control. The
less data moves around, the less opportunity for issues in our system
and the less network bandwidth our platform needs to use.</p>

<h3>Compute</h3>

<p>Compute is our biggest upgrade from V1: Instead of maintaining VMs, we
switched to using <a href="https://azure.microsoft.com/en-us/services/machine-learning/">Azure Machine
Learning</a>
(AML). This is an important switch from IaaS to PaaS, where a lot of the
infrastructure we spent time maintaining is now provisioned and handled
by AML.</p>

<p>AML addresses two of the main problems we set out to solve: Auto-scaling
and isolation for our models. We can run each model on dedicated compute
and then AML <a href="https://docs.microsoft.com/en-us/azure/machine-learning/how-to-set-up-training-targets#run-based-creation">takes care of spinning up the resources required for a
run</a>,
winding them down once the run is over.</p>

<p>Because the configuration for compute is done via code, the dev and
production environments are identical, meaning we don't run into any
issues when graduating a model to production. We can also select the
size of compute we want via this configuration, and so a model that is
more resource intensive can be configured to run with more RAM and/or
more CPU power. AML also gives us statistics on CPU and memory usage,
which helps us right-size compute for each model.</p>

<h3>DevOps</h3>

<p>Both ADF and AML are synced with Git and deployed via two Azure DevOps
<a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/release/?view=azure-devops">release
pipelines</a>.
One of them updates the production ADF instance, the other updates the
AML production instance. We split the two because updating model code
doesn't require any updates to the orchestration. This means, for
example, that for a model bug fix it is enough to deploy to AML without
touching the Data Factory.</p>

<p><img src="https://vladris.com/blog/2020/04/27/devops.png" alt="image"/></p>

<p>Having everything in Git enables self-serve, and brings in the required
engineering rigor: Changes are done through pull requests, we have a
code review process, we don't make manual changes in the production
environment, we have a history of all the changes, and we can rebuild an
environment from scratch if needed.</p>

<h3>Monitoring and alerting</h3>

<p>We are running a production system, and so monitoring and alerting are
key components. For monitoring, we use Azure Monitor/Log Analytics. ADF
orchestrates all our model runs and it <a href="https://docs.microsoft.com/en-us/azure/data-factory/monitor-using-azure-monitor">integrates
natively</a>
with Azure Monitor, where we can define alerts for pipeline failures.</p>

<p>For alerting, we use IcM, the Microsoft-wide incident tracking system.
Pipeline failures generate incident tickets, which alert engineering of
live site issues, like all Azure production services. We are also
providing a Power BI dashboard where stakeholders can see the status of
all models.</p>

<p>Monitoring and alerting help us maintain our service-level agreements
and operational excellence.</p>

<h2>Summary</h2>

<p>In this article we looked at our Version 2 machine learning
infrastructure, going over its key components:</p>

<ul>
<li>We use Azure Data Factory to orchestrate all data movement and model
runs.</li>
<li>We use Azure Data Lake Storage to store both model inputs and
outputs, which allows us to implement granular access control and
easily distribute the data to teams downstream.</li>
<li>We use Azure Machine Learning for compute, which enables
auto-scaling and isolation for model runs.</li>
<li>We use Azure DevOps to deploy from Git, which enables self-serve and
reproducibility.</li>
<li>We use Azure Monitor for production environment monitoring and
alerting.</li>
</ul>

<p>This cloud-native architecture allows us to reliably run ML at scale
with a self-serve environment for our machine learning team, increasing
their productivity while decreasing the resources we need to spend.</p>
]]></description>
      <pubDate>Mon, 27 Apr 2020 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/03/01/azure-data-explorer.html</link>
      <guid>https://vladris.com/blog/2020/03/01/azure-data-explorer.html</guid>
      <title><![CDATA[Azure Data Explorer]]></title>
      <description><![CDATA[<h1>Azure Data Explorer</h1>

<p>This is a cross-post of the article I wrote for Data Science @
Microsoft, <a href="https://medium.com/data-science-at-microsoft/azure-data-explorer-at-the-azure-business-scale-89262ef8c1fd">Azure Data Explorer at the Azure business
scale</a>.</p>

<p>As I mentioned in my previous post, <a href="https://vladris.com/blog/2020/02/01/self-serve-analytics.html"><q>Self-Serve
Analytics</q></a>,
our team uses Azure Data Explorer (ADX) as our main data store. In this
post, I will delve deeply into how we use ADX.</p>

<h2>Use Case</h2>

<p>The <a href="https://docs.microsoft.com/en-us/azure/data-explorer">ADX
documentation</a>
describes it as <q>a fast, fully managed data analytics service for
real-time analysis on large volumes of data streaming from applications,
websites, IoT devices, and more.</q> ADX streams terabytes of data and
enables real-time analytics to be performed on it. In many cases, this
ADX-enabled data is used in the context of ingesting and analyzing
telemetry from various services or endpoints. Our use case for ADX is
different: We use it as the main data store for our big data platform.</p>

<p>We rely on the ingestion capabilities of ADX to pull in terabytes of
data pertaining to the Azure business from various sources. Our data
science team then leverages the fast query capabilities offered by ADX
to explore the data in real time and perform modeling work, which leads
to a better understanding of our customers.</p>

<p>Some of the data points our team uses are already stored in ADX when we
access them, in different clusters managed by other teams. We use the
<a href="https://docs.microsoft.com/en-us/azure/kusto/query/cross-cluster-or-database-queries?pivots=azuredataexplorer">cross-cluster query
capabilities</a>
provided by ADX to join these external data sets with local data.</p>

<p>Our engineering team also relies on the same fast query capabilities of
ADX to power some of our web APIs.</p>

<h2>Ingestion</h2>

<p>We have a well-defined process to bring new data sets into our cluster.
First, we take a one-time snapshot of a potential data set and store it
in a separate cluster (our <em>acquisition</em> cluster), where access is even
further restricted to the small set of individuals tasked with exploring
this new data set. This initial exploration gives us a good sense of
which parts of the data are useful for ingesting on a regular cadence,
and what our data model should look like. We can then create a data
contract with the upstream team to define SLAs and start automating the
data pull.</p>

<p>All data movement is set up in <a href="https://azure.microsoft.com/en-us/services/data-factory/">Azure Data
Factory</a> and
actively monitored.</p>

<h2>DevOps and Analytics</h2>

<p>As I mentioned in my <a href="https://vladris.com/blog/2020/02/01/self-serve-analytics.html">previous
post</a> on
our data environment, we use the <a href="https://docs.microsoft.com/en-us/azure/data-explorer/devops">Azure DevOps ADX
Task</a> to
deploy objects from git. Tables are set up using a
<code>.create-or-merge table</code> script while functions are set up using a
<code>.create-or-alter function</code> script. Both commands are idempotent so we
can replay them even if objects already exist.</p>

<p>As a team, we've standardized on ADX functions for analytics, so all
the reports, KPIs, and metrics our team produces end up implemented as
functions stored in git and deployed using Azure DevOps. The ability to
organize objects in a folder structure helps us group them by focus
area.</p>

<h2>Customer Model</h2>

<p>Not only do we ingest large amounts of data into our main ADX cluster,
we are also processing and enhancing it to build what we call the
<em>customer model</em>.</p>

<p>The customer model consists of three components:</p>

<ul>
<li>A <em>keyring</em>, which helps us tie together various identifiers used
across the business, enabling us to understand, for example, which
company a subscription belongs to.</li>
<li>A set of <em>customer properties</em>, which you can think of as key-value
pairs attached to an identity in our system.</li>
<li>An <em>activity model</em>, which represents a timeline view of various
relevant events for an identity in our system. For example, for a
subscription identifier we have events such as <q>created</q> and
<q>closed</q>.</li>
</ul>

<p><img src="https://vladris.com/blog/2020/03/01/customer-model.png" alt="image"/></p>

<p><em>We use a set of Logic Apps and CosmosDB to process and enhance raw data
into our customer model, which consists of a keyring, customer
properties, and an activity model.</em></p>

<p>The customer model is continuously updated as we ingest new data points
and represents an enhanced view of the raw data. It is implemented as a
small set of (very large) tables and multiple functions to improve
navigation. The expressive ADX function syntax allows us to create
functions that can be combined to produce very complex queries of the
data model.</p>

<p>The workflow of building the model is orchestrated by <a href="https://azure.microsoft.com/en-us/services/logic-apps/">Logic
Apps</a>, which run
ADX functions to join and enhance the raw data. The keyring is an
exception: We build it using
<a href="https://docs.microsoft.com/en-us/azure/cosmos-db/introduction">CosmosDB</a>,
namely the <a href="https://docs.microsoft.com/en-us/azure/cosmos-db/graph-introduction">Gremlin
API</a>,
which can perform graph traversal. We load all identifiers as vertices
and known connections as edges, and then we group each connected
component of the graph into a key group. This gives us the association
across all identities within our system. The output is written back to
ADX.</p>

<p>We consume the customer model through ADX functions. As an example, the
<code>GetRelatedKeysByType()</code> function takes as arguments an identifier value
and an identifier type name and returns all identifiers related to it
from the keyring. We can pass the result of this call to the
<code>GetActivities()</code> function, which also takes as arguments a <code>startDate</code>
datetime and an <code>endDate</code> datetime, to get all activities for the given
ID group within that time range.</p>

<p>Different activities are described by different properties. For example,
a <em>subscription created</em> activity contains, among other things, an Offer
ID, an Offer Type, and a flag indicating whether the subscription was
created as a trial. As another example, a <em>daily usage</em> activity
contains the name of the sold service and consumption units. We use the
ADX
<a href="https://docs.microsoft.com/en-us/azure/kusto/query/packfunction">pack()</a>
function to store these properties as dynamic objects in the underlying
data model, allowing us to maintain a standard schema.</p>

<h2>Compliance</h2>

<p>Because we store some high business impact data sets, such billing data
for Azure services, we must govern who can see different parts of the
data. We set role-base access control (RBAC) at the database level, so
we can place sensitive data sets in dedicated databases.</p>

<p>We can also mark tables as <em>restricted</em>, which limits users to those
with the <a href="https://docs.microsoft.com/en-us/azure/kusto/management/access-control/role-based-authorization">UnrestrictedViewer
role</a>.
In ADX, a Viewer role can view any table in a database except those
marked as restricted. The UnrestrictedViewer role can view any table in
a database regardless of whether it is restricted or not. The ADX team
is also working on enabling table-level access control, which will allow
even more granular RBAC assignments.</p>

<p>We are also leveraging ADX retention policies to ensure data doesn't
stick around forever. In some cases, this is a requirement of the
Microsoft data handling standards that are mandatory across the company.
In other cases, we ensure prototypes and proofs-of-concept are cleaned
up so they don't make their way into our production boundary. I
detailed this in my <a href="https://vladris.com/blog/2020/02/01/self-serve-analytics.html">previous
post</a>,
where I discussed how we move analytics from the prototype Scratch
database (with its 30-day retention policy) to WorkArea and then to
Production.</p>

<h2>Scaling Out</h2>

<p>As more and more workloads are served by our main ADX cluster, we need
to start thinking about performance and scale. We are addressing this in
two main ways: With our approach to data distribution and by looking
into follow clusters.</p>

<p><img src="https://vladris.com/blog/2020/03/01/scale-out.png" alt="image"/></p>

<p><em>Scaling out from a single ADX cluster serving all workloads to multiple
follow clusters supporting different workloads and ADLS for low
frequency, high volume data movement.</em></p>

<p>We used to simply grant access to our data in ADX to teams interested in
consuming it. The problem with this approach is that external teams
might end up running expensive queries against our cluster and disrupt
other operations. This happened frequently in the common scenario of
bulk data movement of the large data sets our team produces. Because of
this, we are no longer granting access to any service principles to ADX.
We allow individuals to come in and explore our data sets but when they
want to start copying it on a regular cadence, we use a different
storage solution: <a href="https://azure.microsoft.com/en-us/services/storage/data-lake-storage/">Azure Data Lake
Storage</a>
(ADLS).</p>

<p>Because our data sets are updated on a daily, weekly, or monthly
cadence, we only need to copy them to ADLS once after an update, and
then other teams can pick them up from there without having an impact on
the performance of our ADX cluster. ADLS provides large scale storage at
very low cost, so it is ideal for this scenario.</p>

<p>The other scaling method we are considering is setting up <a href="https://docs.microsoft.com/en-us/azure/kusto/management/cluster-follower">follow
clusters</a>.
A follower cluster can replicate data from the followed cluster, which
would enable us to offload some workloads to separate compute. By
default, everything is followed, which is redundant for the amount of
data we have, but a follower can be configured to mirror only a subset
of the followed data. We can do this by starting with a caching policy
of 0 (which prevents any data replication), and then selectively
overwrite it for the databases and tables we want to replicate.</p>

<h2>Summary</h2>

<p>In this post, I've discussed our team's use of Azure Data Explorer:</p>

<ul>
<li>Many of our scenarios involve data exploration. That activity,
combined with the large data ingestion and cross-cluster
capabilities of ADX, makes ADX a great data store solution.</li>
<li>We bring data into our cluster via a clearly defined process so that
data loads can be consistently performed and monitored.</li>
<li>We use DevOps to deploy objects to production from git.</li>
<li>We enhance our raw data with a Customer Model, a curated data set
consisting of three major pieces: A keyring, a set of customer
properties, and an activity model. We use ADX functions as an
interface to this data set.</li>
<li>For compliance, we place data in different databases depending on
its classification, and we have granular access control for each
database.</li>
<li>Scaling out, we offload large copy jobs to Azure Data Lake Storage,
and we can create follow clusters to partition the compute load.</li>
</ul>
]]></description>
      <pubDate>Sun, 01 Mar 2020 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/02/01/self-serve-analytics.html</link>
      <guid>https://vladris.com/blog/2020/02/01/self-serve-analytics.html</guid>
      <title><![CDATA[Self-Serve Analytics]]></title>
      <description><![CDATA[<h1>Self-Serve Analytics</h1>

<p>This is a cross-post of the article I wrote for Data Science @
Microsoft, <a href="https://medium.com/data-science-at-microsoft/how-we-built-self-serve-data-environment-tools-with-azure-3951a698fc9d">How we built self-serve data environment tools with
Azure</a>.
Many thanks to my colleague Casey Doyle for editing this into good
shape.</p>

<p>Our team not only helps the engineering org build Azure - we use it,
too, in our data science work. Our team consists of program managers,
data scientists, and data engineers. In this post I describe how our
data engineering team developed a scalable, self-serve analytics
platform for our data science organization.</p>

<p>We maintain a big data platform with all the required data points to
view and understand the Azure business. While we work with multiple data
fabrics (such as Azure SQL and Azure Data Lake Storage), our main
storage solution is Azure Data Explorer (ADX). We use ADX for several
reasons, but two key ones involve the scale of the data we are dealing
with and the exploratory nature of the work our data scientists are
doing. ADX excels at quickly running queries across huge volumes of
data.</p>

<h2>Reproducibility</h2>

<p>When we were a small team, data scientists produced ad hoc reports and
analyses, building queries and running them from their own machines.
This worked for a while, but soon we hit issues of reproducibility: If a
set of queries exists only on one person's machine and that person goes
on vacation, nobody else on the team can reproduce their work.</p>

<p>Of course, this is a well known issue in the software engineering world,
with an industry-standard solution: Source control. As a first step, we
asked everyone on the team to use Git to store their ADX scripts. This
not only enabled capturing <q>canonical</q> queries in a public repository,
it also allowed us to adopt other good practices such as mandatory code
reviews.</p>

<p>Bringing engineering best practices to analytics was the first step
toward a reliable analytics platform.</p>

<h2>Environments</h2>

<p>Another problem we ran into was around the interdependencies among
various data sets. Some reports or metrics took dependencies on the
output of other metrics. But consider a situation in which the dependent
metric consists of one-off exploratory output, while the other is a
monthly report. Without a systematic way of keeping track of what
depends on what, things start to look like Jenga - maybe a critical
piece of an important artifact disappears because the original author
didn't realize anyone cared about it.</p>

<p>To solve this problem, we split our ADX cluster into three different
environments: Scratch, Work Area, and Production.</p>

<p><img src="https://vladris.com/blog/2020/02/01/areas.png" alt="image"/></p>

<p><em>Changes flow from Scratch to Work Area to Production. Production is
read-only for everyone except engineering.</em></p>

<p><em>Scratch</em> is an area open to everyone on the team to do anything they
want, with one important rule: No production dependencies are allowed.
Scratch is used for prototyping, proof-of-concepts, and other
exploratory work. To enforce this, we set a 30-day <a href="https://docs.microsoft.com/en-us/azure/kusto/management/retention-policy">retention
policy</a>.
This ensures that nothing beyond prototypes exists there. Only our team
has access to this area.</p>

<p><em>Work Area</em> is the place data scientists use once they are done
prototyping and have a good idea of what they need to do next. They
still have full access to Work Area but unlike Scratch, data scientists
can share work-in-progress with external stakeholders for user
acceptance testing. If the artifact is a one-time analysis, it stops
here. If it is recurring, for example a monthly report, it graduates to
Production.</p>

<p><em>Production</em> is a locked down environment and only a few data engineers
have Write access to it. This is the equivalent of a production services
environment, where access is restricted such that nobody can
accidentally cause an impact to a live application. In our case, nobody
can accidentally modify a recurring report or key metric others depend
on.</p>

<p>Moving work from Scratch to Work Area to Production ensures dependencies
can only flow in one direction (Scratch can depend on something in
Production, but not vice versa). Quality gates like mandatory code
reviews ensure that whatever makes it to Production meets a high quality
bar.</p>

<p>We also created explicit guidelines for what should go into Production:
Queries should be packaged into functions, tables and functions should
be created with <code>.create-or-alter</code>, and so on.</p>

<h2>Self-Serve</h2>

<p>Because the Production environment is restricted to data engineers,
graduating something to Production first involved a hand-off process: A
data scientist would have to ask the data engineering team to create or
update an entity in the Production environment. This usually meant
creating a work item that had to be prioritized against others.</p>

<p>Our data engineering team is much smaller than our data science
organization (we have about one engineer for every five data
scientists), and so this approach didn't scale very well. To optimize
this, we invested in enabling a self-serve model.</p>

<p>We created an <a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/release/?view=azure-devops">Azure DevOps release
pipeline</a>
that uses the <a href="https://docs.microsoft.com/en-us/azure/data-explorer/devops">ADX
Task</a> to
execute ADX scripts in the git repo against the Production database. We
release from the master branch, but in order for a new script to make it
to master, it must be submitted as a pull request and code review
signoff is required from a member of the engineering team.</p>

<p>With this model, data scientists send a pull request and, once reviewed
by a maintainer of the Production environment, it is automatically
merged and deployed. In contrast to the original hand-off process (via
work items), engineering involvement can be as simple as approving a
pull request. The code review process still ensures that the engineers
who operate the Production environment have a say in what makes it into
that environment and can always request changes to scripts if they
believe, for example, a query can be further optimized.</p>

<h2>Data Movement</h2>

<p>Similar to the analytics needs described above, we needed to orchestrate
data movement. This includes copying data from external sources into our
ADX cluster and running functions on a schedule to produce reports.</p>

<p>Production data movement was originally operated by the engineering
team, and so requests again used to come in the form of work items to be
prioritized and scheduled. But because our data scientists are familiar
with <a href="https://azure.microsoft.com/en-us/services/data-factory/">Azure Data
Factory</a> (ADF)
and use it for data movement in the Work Area environment, we realized
we could enable self-serve capabilities for data movement too, by
leveraging the <a href="https://docs.microsoft.com/en-us/azure/data-factory/continuous-integration-deployment">ADF continuous integration and delivery
setup</a>.
This way, scientists can create ADF pipelines and submit pull requests
that engineers deploy to production.</p>

<p>We are using <a href="https://azure.microsoft.com/en-us/services/monitor/">Azure
Monitor</a> integrated
with IcM, the company-wide incident management system, to monitor the
production pipelines. Azure Monitor <a href="https://docs.microsoft.com/en-us/azure/data-factory/monitor-using-azure-monitor">integrates natively with
ADF</a>.
Our support model entails the engineering team looking at tickets
generated by pipeline failures, which are then restarted to recover from
transient issues. In case of persistent failures, we involve the
original pipeline authors to help debug. This way, the engineering team
operates all Production data movement without having full ownership of
the pipelines.</p>

<p><img src="https://vladris.com/blog/2020/02/01/devops.png" alt="image"/></p>

<p><em>We deploy both Kusto objects and Data Factory pipelines from ADO git
using ADO pipelines. The Production environment is operated by
engineering.</em></p>

<h2>Data Contracts</h2>

<p>But there is still more to it than just deploying and monitoring ADF
pipelines: Bringing external data into the production area of our
cluster means taking an upstream dependency on that data. There are
several properties to be defined for such a dependency, including things
like the service level agreement (SLA) with the upstream provider and
the data classification, which ensures our system stays compliant. The
topic of maintaining compliance in a big data platform deserves an
article by itself, so I won't go into details in this one. The key
point is that in this case, self-serve is not enough - we also need data
contracts.</p>

<p>A <em>data contract</em> specifies all the details of a dependency, whether
upstream or downstream of our platform. As part of the quality gates for
pull requests, we thoroughly review proposed pipelines and in general we
don't allow new
<a href="https://docs.microsoft.com/en-us/azure/data-factory/connector-overview">connectors</a>
to be added with this model. A new connector implies a new dependency,
so before deploying to production we need to ensure we have a contract
in place and that the connector uses the production service principles
the engineering team is maintaining.</p>

<h2>Summary</h2>

<p>In this article we reviewed several of the infrastructure and processes
built by our data engineering team:</p>

<ul>
<li>We brought engineering rigor to our analytics through source
control, code reviews, and automated deployment.</li>
<li>We enabled self-serve by leveraging Azure DevOps.</li>
<li>We similarly enabled self-serve for data movement using ADF CI/CD.</li>
<li>We have processes in place to ensure our data is compliant and that
production dependencies are properly documented.</li>
</ul>

<p>More importantly, we achieved all of the above without maintaining any
custom application code: Our entire solution is built on Azure PaaS
services, which frees up our engineering team to tackle other
challenges, ones we will discuss in future articles.</p>
]]></description>
      <pubDate>Sat, 01 Feb 2020 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2020/01/19/time-and-complexity.html</link>
      <guid>https://vladris.com/blog/2020/01/19/time-and-complexity.html</guid>
      <title><![CDATA[Time and Complexity]]></title>
      <description><![CDATA[<h1>Time and Complexity</h1>

<p>2020 being a leap year, it's a good opportunity to talk about how we
track time. We'll start with that, but this post is as a reflection on
the inherent complexity of the physical world and human societies.</p>

<p>There is a famous blog post, <a href="https://infiniteundo.com/post/25326999628/falsehoods-programmers-believe-about-time">Falsehoods programmers believe about
time</a>,
which covers some well known pitfalls like <em>years have 365 days</em> or
<em>February is always 28 days long</em>. Unfortunately, a lot of software has
such assumptions hardcoded and things go awry.</p>

<p>But before talking about software, let's step back and look at how we
measure time.</p>

<h2>Atomic Clocks</h2>

<p><a href="https://en.wikipedia.org/wiki/Atomic_clock">Atomic clocks</a> provide an
extremely precise measure of the passage of time. These clock don't
gain or lose a single second over hundreds of millions of years. These
devices are beautiful: they can provide a monotonic count of the passage
of time with an incredible precision.</p>

<p>In fact, we have the <a href="https://en.wikipedia.org/wiki/International_Atomic_Time">International Atomic
Time</a> standard,
or TAI, which is defined, according to Wikipedia, by the weighted
average of 400 atomic clocks from over 50 laboratories across the world.
This is an extremely precise measure of time passing on Earth.</p>

<p>It is also not practical enough to be used as the basis of our
calendars. Even with a very accurate, high-resolution, atomic clock, we
still need to account for the fact that the Earth orbits around the Sun
(so we get seasons), and spins around its axis (so we get day and
night). Let's see why there isn't a simple mathematical function from
atomic clock tick to year-month-day-hour-minute-second.</p>

<h2>Leap Years</h2>

<p>Leap years were introduced to account for the fact that Earth's orbit
around the Sun is slightly longer than exactly 365 days. Without
adjusting for this fact, the seasons would gradually shift around the
calendar. But a leap year doesn't necessarily occur every 4 years.
Turns out Earth's orbit is slightly smaller than 365 days and 6 hours,
so adding one day every 4 years would cause seasons to drift the
opposite direction. The leap year rule is actually</p>

<blockquote>
<p>A leap year is every year divisible by 4, except for years divisible
by 100, unless they are also divisible by 400.</p>
</blockquote>

<p>So years like 2020, 2024, 2028 and so on are leap years. But years like
1700, 1800, 1900, are <em>not</em> leap years, because they are divisible by
100. Except 1600, and 2000, which are not only divisible by 100, but
also by 400.</p>

<p>We started with a simple model of a precise, monotonic atomic clock
measuring ticks, but when get to user-friendly time, we end up with
complex business rules that aim to account for the physical world. But
it gets more complicated.</p>

<h2>Leap Seconds and Standards</h2>

<p>If leap years were all there is to it, we could've easily mapped an
atomic clock tick to a precise date time value. But it gets more
complicated. Turns out Earth's rotation is not constant - it is
irregular, and trends towards slow down. Major earthquakes can affect
the momentum of the rotation. Tidal interaction with the moon is also
slowing down the speed of rotation over millions of years.</p>

<p><a href="https://en.wikipedia.org/wiki/Universal_Time">UT1</a>, the Universal Time
standard based on Earth's rotation, is drifting from the
<a href="https://en.wikipedia.org/wiki/Coordinated_Universal_Time">UTC</a>, the
Coordinated Universal Time, which uses atomic clocks to measure time.
Because of this, UTC had to introduce leap seconds. A leap second aims
to bring UTC time (based on atomic clock measurements) back in sync with
UT1 time (time as observed astronomically), so they are not more than 1
second apart.</p>

<p>A leap second adds one second to a day, so we end up with a 61
seconds-long minute. Leap seconds are usually added at the end of the
month, UTC time. For example, on June 30th 2015, the UTC time was, at
some point, 23:59:60. This effectively makes a day 1 second longer.</p>

<p>There is no formula for this: as we measure time both astronomically and
atomically, a standards body decides when a leap second is introduced
and notifies the world every 6 months. In fact, the standard UTC time we
use is, as of the time of this writing, 37 seconds behind the TAI.</p>

<h2>Other Requirements</h2>

<p>Besides the physical realities of measuring time atomically and
astronomically, we have multiple other requirements.</p>

<p>We have daylight saving time, which moves the clocks forward 1 hour in
spring and 1 hour backward in the fall. This creates a 23 hour-long day
in the spring and a 25 hour-long day in the fall (falsehood programmers
believe about time: <em>all days have 24 hours</em>). This is also not standard
across the world: some countries observe daylight saving while others
don't.</p>

<p>We have time zones, which don't neatly divide the earth in 24
equal-width slices, rather are set at geopolitical boundaries. Time
zones aren't even necessarily multiples of 1 hour: India is 5 hour and
30 minutes ahead of UTC.</p>

<p>Also note that daylight saving and time zones get updated: Russia
recently stopped observing daylight saving while China went from 5
different time zones to a single one, even though its geography hasn't
changed.</p>

<h2>Inherent Complexity</h2>

<p>Even with an exact atomic clock, when taking into account year length
and day and night cycles, we have to introduce additional rules to
determine the date and time, like leap years and daylight saving. Not
only that, international standards bodies determine when leap seconds
occur, while countries are free to decide which time zone or time zones
they are using.</p>

<p>I believe this is typical of any non-trivial problem space we tackle
with software. When we try to model the physical world, things get
messy. They get messier with humans in the system: laws, standards, and
expectations introduce other arbitrary rules. Software needs to be
complex to handle the real world.</p>

<h2>Accidental Complexity</h2>

<p>The above conclusion might seem to stand against pretty much everything
I wrote on this blog, where I try to argue for clean and simple code.
Why bother if any real world piece of software is destined to grow
complex? The reason is that there is enough complexity inherent in
dealing with the real world, without us having to introduce more. We
don't need to make things worse than they are. To quote a couple of
lines from <a href="https://www.python.org/dev/peps/pep-0020/">The Zen of
Python</a>:</p>

<blockquote>
<p>Simple is better than complex.</p>

<p>Complex is better than complicated.</p>
</blockquote>

<p>We try to keep things simple. Sometime simple is not enough, we need
complex solutions to complex problems. But at least let's not make them
complicated. A clean, well-crafted system, with rules properly
encapsulated can still be fairly easy to work with. If developers
introduce additional complexity which stems not from the problem domain
but from coding practices, then the ability to reason about and maintain
the system drops precipitously. This is called <em>accidental complexity</em>.</p>

<p>We should always ask ourselves whether the complexity we are dealing
with is inherent or accidental. The former is unavoidable, the latter
should be avoided at all cost.</p>
]]></description>
      <pubDate>Sun, 19 Jan 2020 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/12/27/variance.html</link>
      <guid>https://vladris.com/blog/2019/12/27/variance.html</guid>
      <title><![CDATA[Variance]]></title>
      <description><![CDATA[<h1>Variance</h1>

<p>This blog post is an excerpt from my book, <a href="https://www.manning.com/books/programming-with-types">Programming with
Types</a>. The code
samples are in TypeScript. If you enjoy the article, you can use the
discount code <strong>vlri40</strong> for a 40% discount on the book.</p>

<h2>Subtyping Relationships</h2>

<p>We know that if <code>Triangle extends Shape</code>, then <code>Triangle</code> is a subtype
of <code>Shape</code>. Let's try to answer a few trickier questions:</p>

<ul>
<li>What is the subtyping relationship between the sum types
<code>Triangle | Square</code> and <code>Triangle | Square | Circle</code>?</li>
<li>What is the subtyping relationship between an array of triangles
(<code>Triangle[]</code>) and an array of shapes (<code>Shape[]</code>)?</li>
<li>What is the subtyping relationship between a generic data structure
like <code>List&lt;T&gt;</code>, for <code>List&lt;Triangle&gt;</code> and <code>List&lt;Shape&gt;</code>?</li>
<li>What about the function types <code>() =&gt; Shape</code> and <code>() =&gt; Triangle</code>?</li>
<li>Conversely, what about the function type <code>(argument: Shape) =&gt; void</code>
and the function type <code>(argument: Triangle) =&gt; void</code>?</li>
</ul>

<p>These are important questions, as they tell us which of these types can
be substituted for their subtypes. Whenever we see a function that
expects an argument of one of these types, we should understand whether
we can provide a subtype instead.</p>

<p>The challenge in the above examples is that things aren't as
straightforward as <code>Triangle extends Shape</code>. We are looking at types
which are defined <em>based</em> on <code>Triangle</code> and <code>Shape</code>. <code>Triangle</code> and
<code>Shape</code> are either part of the sum types, or the types of elements of a
collection, or a function's argument types or return types.</p>

<h2>Subtyping and Sum Types</h2>

<p>Let's take the simplest example first, the sum type. Let's say we have
a <code>draw()</code> function which can draw a <code>Triangle</code>, a <code>Square</code>, or a
<code>Circle</code>. Can we pass a <code>Triangle</code> or <code>Square</code> to it? As you might have
guessed, the answer is <q>yes</q>. We can check that such code compiles:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">TriangleType</span><span class="o">:</span><span class="w"> </span><span class="kt">unique</span><span class="w"> </span><span class="nx">symbol</span><span class="p">;</span><span class="w"> </span>
<span class="kd">class</span><span class="w"> </span><span class="nx">Triangle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">[</span><span class="nx">TriangleType</span><span class="p">]</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">    </span><span class="cm">/* Triangle members */</span>
<span class="p">}</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">SquareType</span><span class="o">:</span><span class="w"> </span><span class="kt">unique</span><span class="w"> </span><span class="nx">symbol</span><span class="p">;</span>
<span class="kd">class</span><span class="w"> </span><span class="nx">Square</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">[</span><span class="nx">SquareType</span><span class="p">]</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">    </span><span class="cm">/* Square members */</span>
<span class="p">}</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">CircleType</span><span class="o">:</span><span class="w"> </span><span class="kt">unique</span><span class="w"> </span><span class="nx">symbol</span><span class="p">;</span>
<span class="kd">class</span><span class="w"> </span><span class="nx">Circle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">[</span><span class="nx">CircleType</span><span class="p">]</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">    </span><span class="cm">/* Circle members */</span>
<span class="p">}</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeShape</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Triangle</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">Square</span><span class="p">;</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">draw</span><span class="p">(</span><span class="nx">shape</span><span class="o">:</span><span class="w"> </span><span class="kt">Triangle</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">Square</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">Circle</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>

<span class="nx">draw</span><span class="p">(</span><span class="nx">makeShape</span><span class="p">());</span>
</pre></div>

<p><code>makeShape()</code> returns a <code>Triangle</code> or a <code>Square</code> while <code>draw()</code> accepts
a <code>Triangle</code>, a <code>Square</code> or a <code>Circle</code> (implementations omitted).</p>

<p>We enforce nominal subtyping throughout these examples since we're not
providing full implementations for these types. In practice, they would
have various different properties and methods to distinguish them. We
simulate that with unique symbols for our examples, as leaving the
classes empty would make all of them equivalent due to TypeScript's
<a href="https://en.wikipedia.org/wiki/Structural_type_system">structural
subtyping</a>.</p>

<p>As expected, this code compiles. The opposite doesn't: if we can draw a
<code>Triangle</code> or a <code>Square</code> and we attempt to draw a <code>Triangle</code>, <code>Square</code>,
or <code>Circle</code>, the compiler will complain because we might end up passing
a <code>Circle</code> to the <code>draw()</code> function, which wouldn't know what to do
with it. We can confirm that the below code doesn't compile:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeShape</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Triangle</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">Square</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">Circle</span><span class="p">;</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">draw</span><span class="p">(</span><span class="nx">shape</span><span class="o">:</span><span class="w"> </span><span class="kt">Triangle</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">Square</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>

<span class="nx">draw</span><span class="p">(</span><span class="nx">makeShape</span><span class="p">());</span>
</pre></div>

<p>We flipped the types so <code>makeShape()</code> could also return a <code>Circle</code>,
while <code>draw()</code> no longer accepts a <code>Circle</code>. This no longer compiles.</p>

<p>This means that <code>Triangle | Square</code> is a subtype of
<code>Triangle | Square | Circle</code>: we can always substitute a <code>Triangle</code> or
<code>Square</code> for a <code>Triangle</code>, <code>Square</code>, or <code>Circle</code>, but not the other way
around. This might seem counterintuitive, since <code>Triangle | Square</code> is
<q>less</q> than <code>Triangle | Square | Circle</code>. Whenever we use inheritance,
we end up with a subtype that has more properties than its supertype.
For sum types it works the opposite way: the supertype has more types
than the subtype.</p>

<p><img src="https://vladris.com/blog/2019/12/27/sum-types.png" alt="image"/></p>

<p>Say we have an <code>EquilateralTriangle</code> which inherits from <code>Triangle</code>:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">EquilateralTriangleType</span><span class="o">:</span><span class="w"> </span><span class="kt">unique</span><span class="w"> </span><span class="nx">symbol</span><span class="p">;</span><span class="w"> </span>
<span class="kd">class</span><span class="w"> </span><span class="nx">EquilateralTriangle</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">Triangle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">[</span><span class="nx">EquilateralTriangleType</span><span class="p">]</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">    </span><span class="cm">/* EquilateralTriangle members */</span>
<span class="p">}</span>
</pre></div>

<p>As an exercise, check what happens when we mix sum types with
inheritance. Does <code>makeShape()</code> returning <code>EquilateralTriangle | Square</code>
and <code>draw()</code> accepting <code>Triangle | Square | Circle</code> work? What about
<code>makeShape()</code> returning <code>Triangle | Square</code> and <code>draw()</code> accepting
<code>EquilateralTriangle | Square | Circle</code>?</p>

<h2>Subtyping and Collections</h2>

<p>Now let's look at types which contain a set of values of some other
type. Let's start with arrays: can we pass an array of <code>Triangle</code>
objects to a <code>draw()</code> function which accepts an array of <code>Shape</code>
objects, if <code>Triangle</code> is a subtype of <code>Shape</code>?</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">Shape</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="cm">/* Shape members */</span>
<span class="p">}</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">TriangleType</span><span class="o">:</span><span class="w"> </span><span class="kt">unique</span><span class="w"> </span><span class="nx">symbol</span><span class="p">;</span><span class="w"> </span>
<span class="kd">class</span><span class="w"> </span><span class="nx">Triangle</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">Shape</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">[</span><span class="nx">TriangleType</span><span class="p">]</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="w">    </span><span class="cm">/* Triangle members */</span>
<span class="p">}</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeTriangles</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Triangle</span><span class="p">[];</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">draw</span><span class="p">(</span><span class="nx">shapes</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>

<span class="nx">draw</span><span class="p">(</span><span class="nx">makeTriangles</span><span class="p">());</span>
</pre></div>

<p><code>Triangle</code> is a subtype of <code>Shape</code>. <code>makeTriangles()</code> returns an array
of <code>Triangle</code> objects. <code>draw()</code> accepts an array of <code>Shape</code> objects. We
can use an array of <code>Triangle</code> objects as an array of <code>Shape</code> objects</p>

<p>This might not be surprising, but it is an important observation:
<em>arrays preserve the subtyping relationship of the underlying types they
are storing</em>. As expected, the opposite doesn't work: if we try to pass
an array of <code>Shape</code> objects where an array of <code>Triangle</code> objects is
expected, the code won't compile.</p>

<p><img src="https://vladris.com/blog/2019/12/27/arrays.png" alt="image"/></p>

<p>Arrays are basic types that come out-of-the-box in many programming
languages. What if we define a custom collection, say a <code>LinkedList&lt;T&gt;</code>?</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">LinkedList</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">;</span>
<span class="w">    </span><span class="nx">next</span><span class="o">:</span><span class="w"> </span><span class="kt">LinkedList</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">append</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">LinkedList</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">next</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">LinkedList</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">next</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeTriangles</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">LinkedList</span><span class="o">&lt;</span><span class="nx">Triangle</span><span class="o">&gt;</span><span class="p">;</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">draw</span><span class="p">(</span><span class="nx">shapes</span><span class="o">:</span><span class="w"> </span><span class="kt">LinkedList</span><span class="o">&lt;</span><span class="nx">Shape</span><span class="o">&gt;</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>

<span class="nx">draw</span><span class="p">(</span><span class="nx">makeTriangles</span><span class="p">());</span>
</pre></div>

<p><code>LinkedList&lt;T&gt;</code> is a generic linked list collection. <code>makeTriangle()</code>
now returns a linked list of traingles. <code>draw()</code> accepts a linked list
of shapes. This code compiles.</p>

<p>Even without an out-of-the-box type, TypeScript correctly establishes
that <code>LinkedList&lt;Triangle&gt;</code> is a subtype of <code>LinkedList&lt;Shape&gt;</code>. Like
before, the opposite doesn't compile - we can't pass a
<code>LinkedList&lt;Shape&gt;</code> as a <code>LinkedList&lt;Triangle&gt;</code>.</p>

<blockquote>
<p><strong>Covariance</strong></p>

<p>A type which preserves the subtyping relationship of its underlying
type is called <em>covariant</em>. An array is covariant, because it
preserves the subtyping relationship: <code>Triangle</code> is a subtype of
<code>Shape</code>, so <code>Triangle[]</code> is a subtype of <code>Shape[]</code>.</p>
</blockquote>

<p>Various languages behave differently when dealing with arrays and
collections like <code>LinkedList&lt;T&gt;</code>. For example, in C# we would have to
explicitly state covariance for a type like <code>LinkedList&lt;T&gt;</code> by declaring
an interface and using the <code>out</code> keyword (<code>ILinkedList&lt;out T&gt;</code>),
otherwise the compiler will not deduce the subtyping relationship.</p>

<p>An alternative to covariance is to simply ignore the subtyping
relationship between two given types and consider a <code>LinkedList&lt;Shape&gt;</code>
and <code>LinkedList&lt;Triangle&gt;</code> as types with no subtyping relationship
between them (neither is a subtype of the other). This is not the case
in TypeScript, but it is in C#, where a <code>List&lt;Shape&gt;</code> and a
<code>List&lt;Triangle&gt;</code> have no subtyping relationship.</p>

<blockquote>
<p><strong>Invariance</strong></p>

<p>A type which ignores the subtyping relationship of its underlying type
is called invariant. A C# <code>List&lt;T&gt;</code> is invariant, because it ignores
the subtyping relationship <q><code>Triangle</code> is a subtype of <code>Shape</code></q>, so
<code>List&lt;Shape&gt;</code> and <code>List&lt;Triangle&gt;</code> have no subtype-supertype
relationship.</p>
</blockquote>

<p>Now that we looked at how collections relate to each other in terms of
subtyping and saw two common types of variance, let's see how function
types related to each other.</p>

<h2>Subtyping and Function Return Types</h2>

<p>We'll start with the simpler case first: see what substitutions we can
make between a function that returns a <code>Triangle</code> and a function that
returns a <code>Shape</code>. We'll declare two factory functions, a <code>makeShape()</code>
which returns a <code>Shape</code> and a <code>makeTriangle()</code> which returns a
<code>Triangle</code>.</p>

<p>We'll then implement a <code>useFactory()</code> function which takes a function
of type <code>() =&gt; Shape</code> as argument and returns a <code>Shape</code>. We'll try
passing <code>makeTriangle()</code> to it:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeTriangle</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Triangle</span><span class="p">;</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeShape</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Shape</span><span class="p">;</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">useFactory</span><span class="p">(</span><span class="nx">factory</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">Shape</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Shape</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">factory</span><span class="p">();</span>
<span class="p">}</span>

<span class="kd">let</span><span class="w"> </span><span class="nx">shape1</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useFactory</span><span class="p">(</span><span class="nx">makeShape</span><span class="p">);</span>
<span class="kd">let</span><span class="w"> </span><span class="nx">shape2</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useFactory</span><span class="p">(</span><span class="nx">makeTriangle</span><span class="p">);</span>
</pre></div>

<p><code>useFactory()</code> takes a function with no arguments which returns a
<code>Shape</code> and calls it. Both <code>makeTriangle()</code> and <code>makeShape()</code> can be
used as arguments to <code>useFactory()</code>.</p>

<p>Nothing out of the ordinary here: we can pass a function that returns a
<code>Triangle</code> as a function that returns a <code>Shape</code>, because the return
value (a <code>Triangle</code>) is a subtype of <code>Shape</code>, so we can assign it to a
<code>Shape</code>.</p>

<p><img src="https://vladris.com/blog/2019/12/27/function-returns.png" alt="image"/></p>

<p>The opposite doesn't work: if we change our <code>useFactory()</code> to expect a
<code>() =&gt; Triangle</code> argument and try to pass it <code>makeShape()</code>, the code
won't compile:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeTriangle</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Triangle</span><span class="p">;</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">makeShape</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Shape</span><span class="p">;</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">useFactory</span><span class="p">(</span><span class="nx">factory</span><span class="o">:</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">Triangle</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Triangle</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">factory</span><span class="p">();</span>
<span class="p">}</span>

<span class="kd">let</span><span class="w"> </span><span class="nx">shape1</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useFactory</span><span class="p">(</span><span class="nx">makeShape</span><span class="p">);</span>
<span class="kd">let</span><span class="w"> </span><span class="nx">shape2</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">useFactory</span><span class="p">(</span><span class="nx">makeTriangle</span><span class="p">);</span>
</pre></div>

<p>We replaced <code>Shape</code> with <code>Triangle</code> in the <code>useFactory()</code> definition.
The code fails to compile: we can't use <code>makeShape()</code> as a
<code>() =&gt; Triangle</code>.</p>

<p>This is again pretty straightforward: we can't use <code>makeShape()</code> as a
function of type <code>() =&gt; Triangle</code> because <code>makeShape()</code> returns a
<code>Shape</code> object. That object could be a <code>Triangle</code>, but it might be a
<code>Square</code>. <code>useFactory()</code> promises to return a <code>Triangle</code>, so it can't
return a supertype of <code>Triangle</code>. It could, of course, return a subtype,
like <code>EquilateralTriangle</code>, given a <code>makeEquilateralTriangle()</code>.</p>

<p>Functions are covariant in their return types. In other words, if
<code>Triangle</code> is a subtype of <code>Shape</code>, a function type like
<code>() =&gt; Triangle</code> is a subtype of a function <code>() =&gt; Shape</code>. Note that the
function types don't have to describe functions that don't take any
arguments. If <code>makeTriangle()</code> and <code>makeShape()</code> both took a couple of
number arguments, they would still be covariant as we just saw.</p>

<p>This is the behavior followed by most mainstream programming languages.
The same rules are followed for overriding methods in inherited types,
changing their return type. If we implement a <code>ShapeMaker</code> class which
provides a <code>make()</code> method that returns a <code>Shape</code>, we can override it in
a derived class <code>TriangleMaker</code> to return <code>Triangle</code> instead. The
compiler will allow this, as calling either of the <code>make()</code> methods will
give us a <code>Shape</code> object:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">ShapeMaker</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">make</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Shape</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Shape</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span><span class="w"> </span><span class="nx">TriangleMaker</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">ShapeMaker</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">make</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">Triangle</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Triangle</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This is, again, allowed behavior in most mainstream programming
languages, as most consider functions covariant in their return type.
Let's now see what happens to function types whose argument types are
subtypes of each other.</p>

<h2>Subtyping and Function Argument Types</h2>

<p>We'll turn things inside out, so instead of a function that returns a
<code>Shape</code> and a function that returns a <code>Triangle</code>, we'll take a function
that takes a <code>Shape</code> as argument and a function that takes a <code>Triangle</code>
as argument. We'll call these <code>drawShape()</code> and <code>drawTriangle()</code>. How
do <code>(argument: Shape) =&gt; void</code> and <code>(argument: Triangle) =&gt; void</code> relate
to one another?</p>

<p>Let's introduce another function, <code>render()</code>, which takes as arguments
a <code>Triangle</code> and an <code>(argument: Triangle) =&gt; void</code> function. It simply
calls the given function with the given <code>Triangle</code>:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">drawShape</span><span class="p">(</span><span class="nx">shape</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">drawTriangle</span><span class="p">(</span><span class="nx">triangle</span><span class="o">:</span><span class="w"> </span><span class="kt">Triangle</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">render</span><span class="p">(</span>
<span class="w">    </span><span class="nx">triangle</span><span class="o">:</span><span class="w"> </span><span class="kt">Triangle</span><span class="p">,</span>
<span class="w">    </span><span class="nx">drawFunc</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">argument</span><span class="o">:</span><span class="w"> </span><span class="kt">Triangle</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">drawFunc</span><span class="p">(</span><span class="nx">triangle</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p><code>drawShape()</code> takes a <code>Shape</code> argument, <code>drawTriangle()</code> takes a
<code>Triangle</code> argument. <code>render()</code> expects a <code>Triangle</code> and a function that
takes a <code>Triangle</code> as argument. <code>render()</code> simply calls the provided
function passing it the triangle it received.</p>

<p>Here comes the interesting bit: in this case, we can safely pass
<code>drawShape()</code> to the <code>render()</code> function! That means we can use a
<code>(argument: Shape) =&gt; void</code> where an <code>(argument: Triangle) =&gt; void</code> is
expected.</p>

<p>Logically it makes sense: we have a <code>Triangle</code> and we pass it to a
drawing function which can use it as an argument. If the function itself
expects a <code>Triangle</code>, like our <code>drawTriangle()</code> function, then of course
it works. But it should also work for a function which expects a
supertype of <code>Triangle</code>: <code>drawShape()</code> wants a shape - any shape - to
draw. Since it doesn't use anything that's triangle-specific, it is
more general than <code>drawTriangle()</code>, it can accept any shape as argument,
be it <code>Triangle</code> or <code>Square</code>. So in this particular case, the subtyping
relationship is reversed.</p>

<blockquote>
<p><strong>Contravariance</strong></p>

<p>A type which reverses the subtyping relationship of its underlying
type is called <em>contravariant</em>. In most programming languages,
functions are contravariant with regards to their arguments. A
function which expects a <code>Triangle</code> as argument can be substituted
with a function which expects a <code>Shape</code> as argument. The relationship
of the functions is the reverse of the relationship of the argument
types: if <code>Triangle</code> is a subtype <code>Shape</code>, the type of a function
taking a <code>Triangle</code> as an argument is a supertype of the type of a
function taking a <code>Shape</code> as an argument.</p>
</blockquote>

<p><img src="https://vladris.com/blog/2019/12/27/function-arguments.png" alt="image"/></p>

<p>We said <q>most programming languages</q> in the definition above. A
notable exception is TypeScript. In TypeScript, we can also do the
opposite: pass a function which expects a subtype instead of a function
which expects a supertype. This was an explicit design choice, to
facilitate common JavaScript programming patterns. It can lead to
runtime issues though. Let's look at an example. We'll first define a
method <code>isRightAngled()</code> on our <code>Triangle</code> type, which would determine
whether a given instance describes a right-angled triangle. The
implementation of the method is not important:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">Shape</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="cm">/* Shape members */</span>
<span class="p">}</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="nx">TriangleType</span><span class="o">:</span><span class="w"> </span><span class="kt">unique</span><span class="w"> </span><span class="nx">symbol</span><span class="p">;</span><span class="w"> </span>
<span class="kd">class</span><span class="w"> </span><span class="nx">Triangle</span><span class="w"> </span><span class="k">extends</span><span class="w"> </span><span class="nx">Shape</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">[</span><span class="nx">TriangleType</span><span class="p">]</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>

<span class="w">    </span><span class="nx">isRightAngled</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>

<span class="w">        </span><span class="cm">/* Determine whether it is a right-angled triangle */</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span>

<span class="w">    </span><span class="cm">/* More Triangle members */</span>
<span class="p">}</span>
</pre></div>

<p>Now let's reverse the drawing example and let's say our <code>render()</code>
function expects a <code>Shape</code> instead of a <code>Triangle</code>, and a function which
can draw shapes <code>(argument: Shape) =&gt; void</code> instead of a function which
can only draw triangles <code>(argument: Triangle) =&gt; void</code>:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">drawShape</span><span class="p">(</span><span class="nx">shape</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">drawTriangle</span><span class="p">(</span><span class="nx">triangle</span><span class="o">:</span><span class="w"> </span><span class="kt">Triangle</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="p">;</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">render</span><span class="p">(</span>
<span class="w">    </span><span class="nx">shape</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="p">,</span>
<span class="w">    </span><span class="nx">drawFunc</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">argument</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">drawFunc</span><span class="p">(</span><span class="nx">shape</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p><code>drawShape()</code> and <code>drawTriangle()</code> are just like before. <code>render()</code> now
expects a <code>Shape</code> and a function that takes a <code>Shape</code> as argument.</p>

<p>Here's how we can cause a runtime error: we can define <code>drawTriangle()</code>
to actually use something that is triangle-specific, like the
<code>isRightAngled()</code> method we just added. We then call <code>render()</code> with a
<code>Shape</code> object (not a <code>Triangle</code>) and <code>drawTriangle()</code>.</p>

<p>Now <code>drawTriangle()</code> will receive a <code>Shape</code> object and attempt to call
<code>isRightAngled()</code> on it, but since the <code>Shape</code> is not a <code>Triangle</code>, this
will cause an error:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">drawTriangle</span><span class="p">(</span><span class="nx">triangle</span><span class="o">:</span><span class="w"> </span><span class="kt">Triangle</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">triangle</span><span class="p">.</span><span class="nx">isRightAngled</span><span class="p">());</span>
<span class="w">    </span><span class="cm">/* ... */</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">render</span><span class="p">(</span>
<span class="w">    </span><span class="nx">shape</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="p">,</span><span class="w">    </span>
<span class="w">    </span><span class="nx">drawFunc</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">argument</span><span class="o">:</span><span class="w"> </span><span class="kt">Shape</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span><span class="w">    </span>
<span class="w">    </span><span class="nx">drawFunc</span><span class="p">(</span><span class="nx">shape</span><span class="p">);</span><span class="w">  </span>
<span class="p">}</span>

<span class="nx">render</span><span class="p">(</span><span class="ow">new</span><span class="w"> </span><span class="nx">Shape</span><span class="p">(),</span><span class="w"> </span><span class="nx">drawTriangle</span><span class="p">);</span>
</pre></div>

<p>We can pass a <code>Shape</code> and <code>drawTriangle()</code> to <code>render()</code>. This code will
compile but it will fail at runtime with a JavaScript error, since the
runtime won't be able to find <code>isRightAngled()</code> on the <code>Shape</code> object
we gave to <code>drawTriangle()</code>. This is not ideal but, as mentioned before,
it was a conscious decision made during the implementation of
TypeScript.</p>

<p>In TypeScript, if <code>Triangle</code> is a subtype of <code>Shape</code>, a function of type
<code>(argument: Shape) =&gt; void</code> and a function of type
<code>(argument: Triangle) =&gt; void</code> can be substituted for each other.
Effectively, they are both subtypes of each other. This property is
called <em>bivariance</em>.</p>

<blockquote>
<p><strong>Bivariance</strong></p>

<p>Types are <em>bivariant</em> if, from the subtyping relationship of their
underlying types, they become subtypes of each other. In TypeScript,
if <code>Triangle</code> is a subtype of <code>Shape</code>, the function types
<code>(argument: Shape) =&gt; void</code> and <code>(argument: Triangle) =&gt; void</code> are
subtypes of each other.</p>
</blockquote>

<p><img src="https://vladris.com/blog/2019/12/27/bivariance.png" alt="image"/></p>

<p>Again, the bivariance of functions with respect to their arguments in
TypeScript allows incorrect code to compile. We rely on static type
checking to eliminate runtime errors at compile time. For TypeScript it
was a deliberate design decision to enable common JavaScript programming
patterns.</p>

<h2>Summary</h2>

<p>We looked at what types can be substituted with what other types. While
subtyping is straight-forward when dealing with simple inheritance,
things get more complicated when we add types parameterized on other
types. These could be collections, function types, or other generic
types. The way the subtyping relationships of these parameterized types
is removed, preserved, reversed, or made two-way based on the
relationship of their underlying types is called <em>variance</em>.</p>

<ul>
<li><em>Invariant</em> types ignore the subtyping relationship of their
underlying types.</li>
<li><em>Covariant</em> types preserve the subtyping relationship of their
underlying types. If <code>Triangle</code> is a subtype of <code>Shape</code>, an array of
type <code>Triangle[]</code> is a subtype of an array of type <code>Shape[]</code>. In
most programming languages, function types are covariant in their
return types.</li>
<li><em>Contravariant</em> types reverse the subtyping relationship of their
underlying types. If <code>Triangle</code> is a subtype of <code>Shape</code>, the
function type <code>(argument: Shape) =&gt; void</code> is a subtype of the
function type <code>(argument: Triangle) =&gt; void</code> in most languages. This
is not true for TypeScript, where function types are bivariant with
regards to their argument types.</li>
<li><em>Bivariant</em> types are subtypes of each other when their underlying
types are in a subtyping relationship. If <code>Triangle</code> is a subtype of
<code>Shape</code>, the function type <code>(argument: Shape) =&gt; void</code> and the
function type <code>(argument: Triangle) =&gt; void</code> are subtypes of each
other (functions of both types can be substituted for one another).</li>
</ul>

<p>While some common rules exist across programming languages, there is no
one way to support variance. You should understand what the type system
of your programming language does and how it establishes subtyping
relationships. This is important to know, as these rules tell us what
can be substituted for what. Do you need to implement a function to
transform a <code>List&lt;Triangle&gt;</code> into a <code>List&lt;Shape&gt;</code>, or can you just use
the <code>List&lt;Triangle&gt;</code> as-is? It all depends on the variance of <code>List&lt;T&gt;</code>
in your programming language of choice.</p>
]]></description>
      <pubDate>Fri, 27 Dec 2019 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/12/08/notes-on-data-engineering.html</link>
      <guid>https://vladris.com/blog/2019/12/08/notes-on-data-engineering.html</guid>
      <title><![CDATA[Notes on Data Engineering]]></title>
      <description><![CDATA[<h1>Notes on Data Engineering</h1>

<p>For over a year now I've been the architect for the Customer Growth and
Analytics team in Azure, scaling out our big data platform as our team
grows and matures. I'm going to share a few observations on some of the
main problems we've been solving, problems which I believe are fairly
universal: I attended the <a href="https://conferences.oreilly.com/strata-data-ai">Strata Data
Conference</a> this year
and speakers from many other companies were talking about similar
problems and the solutions they were implementing.</p>

<p>Not too long ago, the major challenges were around storing and
processing data at scale. Since this has been more or less commoditized
in the past few years, especially with the emergence of cloud providers,
it's interesting to think about how the big data landscape evolved and
what are some of the present challenges. I list some of them below.</p>

<h2>Compliance</h2>

<p>Proper handling of data assets is a top priority for Microsoft and
should be for everyone. There are several aspects I consider to be part
of compliance.</p>

<p>First, there are regulatory obligations, probably the best-known example
being GDPR. In order to be compliant with GDPR, a data platform needs to
have the ability to <q>forget</q> about a user if the user so desires. A
data platform needs to support all capabilities required by regulations
of the countries it gets its data from. There are many other
regulations, and new ones can come up at any time. Staying compliant is
maybe the most important work for a data platform.</p>

<p>Next, there is access control: who gets to see what data. There are
various types of data for which access should be restricted. Personally
Identifiable Information (PII) is data that can be used to identify a
particular person, like name or email address. High Business Impact
(HBI) is data relevant to the business, like revenue numbers, devices
sold etc. Different companies use different taxonomies to classifies
their data assets, but regardless, in the big data space, it is a non
trivial problem to ensure that only people who are allowed to access a
certain data set are able to do so. If access to sensitive data sets is
under a need-to-know basis, and we create one security group per
dataset, just managing those security groups is hard in itself. On top
of that, people move and organizations change and that can impact who
has access to the data too.</p>

<p>I believe there is a lot of room to improve and innovate in this space.
There are many existing solutions to handle both regulatory and access
control requirements, but nothing that feels like <em>it just works</em>, and
definitely little in terms of industry standards.</p>

<h2>Metadata</h2>

<p>As the data volume grows, organizing it becomes a big challenge. There
is a need for an additional layer of data about the data, or metadata.
There are several very important pieces of information which are not
readily available in the data itself that a big data platform must
provide.</p>

<p>First, there is simply the descriptions of various datasets: what the
various columns are, how often is the data refreshed, how fresh the data
is etc. There also needs to be an ability to search this metadata in
order to find relevant data available in the system.</p>

<p>Next, there is data lineage. Where did the data come from and how was it
sourced? This has compliance implications: for example if end users
agree to share telemetry data for the purpose of improving the product,
that data should not be used for other purposes.</p>

<p>Also for compliance purposes, various datasets and columns have to be
tagged as containing PII or other sensitive information so the system
can automatically lock down or purge this type of sensitive data when
needed.</p>

<p>Organizing data at scale also requires some amount of information
architecture. One aspect of this is controlled taxonomies: clear
definitions of what various business terms and data pieces mean, so
everyone working in the space shares the same understanding.</p>

<p><a href="https://azure.microsoft.com/en-us/services/data-catalog/">Azure Data
Catalog</a> is
the Azure offering in this space.</p>

<h2>Heterogeneity by Design</h2>

<p>There is no one-size-fits-all data fabric. Each storage solution has
some workflows it was optimized for and some it's not so great at.
It's next to impossible to say that absolutely everything will be
running on one single solution, be that SQL, NoSQL, HDFS, or something
else. Some workflows need massive scale (processing terabytes of data),
some workflows need fast reads (serving a website). Teams upstream will
expose data from different storage solutions while teams downstream will
expect it in different storage solutions...</p>

<p>Standardizing on a unique storage solution is unfeasible, so the next
best thing to do is to standardize on the tooling to move the data
around and ensure that it is easy to operate: make it easy to create a
new data movement pipeline, provide monitoring, alerting etc. Since data
movement is a necessity, it must be as reliable as possible.</p>

<p>Our team uses <a href="https://azure.microsoft.com/en-us/services/data-factory/">Azure Data
Factory</a> for
orchestrating data movement at scale.</p>

<h2>DevOps</h2>

<p>Another major bucket of work is bringing engineering rigor to workflows
supported by other disciplines like data science and machine learning
engineering. Again, with a small team, it is relatively easy to create
ad-hoc reports and run ad-hoc ML but this approach doesn't scale. Once
production systems depend on the output.</p>

<p>This is a solved problem in the software engineering field: source
control, code reviews, continuous integration and so on. But
non-engineering disciplines are not accustomed to this type of workflow
so there is definitely a need to educate, support, and create similar
devops workflows. Analytics and ML ultimately reduce to code (SQL
queries, Python, R etc.) and should be handled just as production code.</p>

<p>Our team supports these types of workflows using <a href="https://azure.microsoft.com/en-us/services/devops/">Azure
DevOps</a> with
pipelines that can deploy ML and analytics from git to our production
environment.</p>

<h2>Data Quality</h2>

<p>The last topic I will cover is data quality. The quality of all
analytics and machine learning outputs depends on the quality of the
underlying data.</p>

<p>There are multiple aspects to data quality. One set of definitions is
given by the article <a href="https://smartbridge.com/data-done-right-6-dimensions-of-data-quality/">Data Done Right: 6 Dimensions of Data
Quality</a>:</p>

<ul>
<li>Completeness - the dataset is not missing any required data.</li>
<li>Consistency - the data is consistent across multiple datasets.</li>
<li>Conformity - all data in the right format, within the right value
ranges etc.</li>
<li>Accuracy - the data accurately represents the domain being modelled.</li>
<li>Integrity - the data is valid across all relationships and datasets.</li>
<li>Timeliness - the data available when expected and datasets are not
delayed.</li>
</ul>

<p>A reliable data platform can run various types of data quality tests on
the managed datasets, both at scheduled times and during ingress. Issues
have to be reported and the overall state of the data quality made
visible through a dashboard so stakeholders can easily see which
datasets currently have problems and what are the potential implications
of that.</p>

<p>As of today, this seems to be a big gap in terms of industry-wide
standard solutions. Data engineering teams develop their bespoke data
test runners for their scenarios. There are many open source solutions,
but we don't have the equivalent of JUnit yet, nor a common language
for specifying tests and assertions.</p>

<h2>Conclusions</h2>

<p>In the following years, I expect we will have both better tooling for
some of these problems and better defined industry-wide standards. As I
mentioned at the beginning of this post, not long ago, just storing and
processing huge amounts of data was a hard problem. Today, the main
challenges are around organizing and managing data. I fully expect that
in the near future we will have out-of-the-box solutions for all these
problems and a new set of challenges will emerge.</p>
]]></description>
      <pubDate>Sun, 08 Dec 2019 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/11/18/unit-testing-101.html</link>
      <guid>https://vladris.com/blog/2019/11/18/unit-testing-101.html</guid>
      <title><![CDATA[Unit Testing 101]]></title>
      <description><![CDATA[<h1>Unit Testing 101</h1>

<p>I wrote a while back about <a href="https://vladris.com/blog/2017/11/09/notes-on-unit-testing.html">unit
testing</a>
from a philosophical perspective. This post is going to be more
pragmatic. My team is currently doing some MQ work which includes
improving our unit test story across the codebase. I put together a
short unit tests 101 presentation outlining some key principles:</p>

<ul>
<li>Run with each build.</li>
<li>100% reliability.</li>
<li>Test the public interface.</li>
</ul>

<h2>Run with Each Build</h2>

<p>Unit tests that don't run aren't very useful. I've seen projects
before where a unit test project does exist but the tests only run if
manually executed.</p>

<p>The problem with this approach is that tests can stay not running for
days/weeks/months, and when they finally run, a bunch of them fail. Good
luck finding the change that introduced the regression. And wait, were
we running with that behavior all this time?</p>

<p>The biggest bang for the buck is making sure unit tests run as part of a
continuous integration build and pull requests get auto-rejected if a
unit test fails.</p>

<h2>100% Reliability</h2>

<p>Once unit tests run with each build, the next most important thing to
look into is ensuring they pass consistently. Flaky unit tests are bad
because there's no easy way to tell if a test run failed because of a
regression or a flaky test. Worst, if flaky tests are the standard,
engineers start ignoring the results. Hard to distill the signal from
the noise in those situations. Merge policies become more lax - after
all, we can't demand 100% green if some unit tests randomly fail.</p>

<p>But stepping back, when are tests flaky? When they perform IO. Hitting
the network, connecting to a database, reading a file, these are all
cases in which a transient issue outside of our control can cause a test
to fail. That's why unit tests shouldn't perform IO, rather they
should work against mocks.</p>

<p>Let's take, as an example, a method which performs a GET request and
logs to the console whether the request was successful:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Example</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="kt">var</span><span class="w"> </span><span class="n">client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HttpClient</span><span class="p">();</span>
<span class="w">        </span><span class="kt">var</span><span class="w"> </span><span class="n">response</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">client</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span>
<span class="w">            </span><span class="s">"https://www.example.com"</span><span class="p">).</span><span class="n">Result</span><span class="p">;</span>

<span class="w">        </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>In its current form, the method isn't really testable. Writing code
without thinking about testability yields such methods. We can refactor
this to be more testable. First, let's put all IO behind interfaces:</p>
<div class="highlight"><pre><span/><span class="k">interface</span><span class="w"> </span><span class="n">IHttpClient</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Task</span><span class="o">&lt;</span><span class="n">HttpResponseMessage</span><span class="o">&gt;</span><span class="w"> </span><span class="n">GetAsync</span><span class="p">(</span><span class="kt">string</span><span class="w"> </span><span class="n">url</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">interface</span><span class="w"> </span><span class="n">IOutput</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">void</span><span class="w"> </span><span class="nf">WriteLine</span><span class="p">(</span><span class="kt">bool</span><span class="w"> </span><span class="k">value</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>We can update our <code>Example</code> to use these interfaces instead of directly
working with <code>HttpClient</code> and <code>Console</code>:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Example</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="n">IHttpClient</span><span class="w"> </span><span class="n">client</span><span class="p">;</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="n">IOutput</span><span class="w"> </span><span class="n">output</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Example</span><span class="p">(</span><span class="n">IHttpClient</span><span class="w"> </span><span class="n">client</span><span class="p">,</span><span class="w"> </span><span class="n">IOutput</span><span class="w"> </span><span class="n">output</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="n">client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">client</span><span class="p">;</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="n">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">output</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="kt">var</span><span class="w"> </span><span class="n">response</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">client</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span>
<span class="w">            </span><span class="s">"https://www.example.com"</span><span class="p">).</span><span class="n">Result</span><span class="p">;</span>

<span class="w">        </span><span class="n">output</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">response</span><span class="p">.</span><span class="n">IsSuccessStatusCode</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>We add adapters between the interfaces and the actual implementations:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">HttpClientWrapper</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">IHttpClient</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="n">HttpClient</span><span class="w"> </span><span class="n">client</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">HttpClient</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">Task</span><span class="o">&lt;</span><span class="n">HttpResponseMessage</span><span class="o">&gt;</span><span class="w"> </span><span class="n">GetAsync</span><span class="p">(</span><span class="kt">string</span><span class="w"> </span><span class="n">url</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">client</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="n">url</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">class</span><span class="w"> </span><span class="nc">ConsoleOutput</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">IOutput</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">WriteLine</span><span class="p">(</span><span class="kt">bool</span><span class="w"> </span><span class="k">value</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="k">value</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>With these adapters, in our production code we can put together an
instance of <code>Example</code> that works just like the original, but which is
componentized enough that we can actually test it:</p>
<div class="highlight"><pre><span/><span class="kt">var</span><span class="w"> </span><span class="n">example</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Example</span><span class="p">(</span>
<span class="w">    </span><span class="k">new</span><span class="w"> </span><span class="nf">HttpClientWrapper</span><span class="p">(),</span>
<span class="w">    </span><span class="k">new</span><span class="w"> </span><span class="nf">ConsoleOutput</span><span class="p">());</span>
<span class="n">example</span><span class="p">.</span><span class="n">Get</span><span class="p">();</span>
</pre></div>

<p>In our test code, we can use a framework like Moq<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup> to set up mocks
and verify that the expected calls happen:</p>
<div class="highlight"><pre><span/><span class="kt">var</span><span class="w"> </span><span class="n">mockClient</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Mock</span><span class="o">&lt;</span><span class="n">IHttpClient</span><span class="o">&gt;</span><span class="p">();</span>
<span class="n">mockClient</span><span class="p">.</span><span class="n">Setup</span><span class="p">(</span>
<span class="w">    </span><span class="n">client</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">client</span><span class="p">.</span><span class="n">GetAsync</span><span class="p">(</span><span class="s">"https://www.example.com"</span><span class="p">))</span>
<span class="w">    </span><span class="p">.</span><span class="n">Returns</span><span class="p">(</span><span class="n">Task</span><span class="p">.</span><span class="n">FromResult</span><span class="p">(</span>
<span class="w">        </span><span class="k">new</span><span class="w"> </span><span class="n">HttpResponseMessage</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="n">StatusCode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HttpStatusCode</span><span class="p">.</span><span class="n">OK</span>
<span class="w">        </span><span class="p">}));</span>

<span class="kt">var</span><span class="w"> </span><span class="n">mockOutput</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Mock</span><span class="o">&lt;</span><span class="n">IOutput</span><span class="o">&gt;</span><span class="p">();</span>
<span class="n">mockOutput</span><span class="p">.</span><span class="n">Setup</span><span class="p">(</span>
<span class="w">    </span><span class="n">output</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">output</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span>
<span class="w">        </span><span class="n">It</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="kt">bool</span><span class="o">&gt;</span><span class="p">(</span><span class="k">value</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">value</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">true</span><span class="p">)));</span>

<span class="kt">var</span><span class="w"> </span><span class="n">example</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Example</span><span class="p">(</span>
<span class="w">    </span><span class="n">mockClient</span><span class="p">.</span><span class="n">Object</span><span class="p">,</span>
<span class="w">    </span><span class="n">mockOutput</span><span class="p">.</span><span class="n">Object</span><span class="p">);</span>
<span class="n">example</span><span class="p">.</span><span class="n">Get</span><span class="p">();</span>

<span class="n">mockOutput</span><span class="p">.</span><span class="n">VerifyAll</span><span class="p">();</span>
</pre></div>

<p>The above code sets up an <code>IHttpClient</code> mock implementation which so
that when <code>GetAsync()</code> is called with the argument
<code>https://www.example.com</code> it returns a <code>Task&lt;HttpResponseMessage&gt;</code> with
a <code>StatusCode</code> of <code>HttpStatusCode.OK</code>. The code also sets up an
<code>IOutput</code> mock which expects a <code>WriteLine()</code> call with a <code>true</code>
argument.</p>

<p>We can initialize an instance of <code>Example</code> with these mocks, call
<code>Get()</code>, then verify <code>mockOutput</code> was used as expected.</p>

<h3>Design for Testability</h3>

<p>The general steps for making code testable:</p>

<ul>
<li>Extract interface (if one doesn't exist already).</li>
<li>Create adapters if concrete implementation doesn't implement an
interface.</li>
<li>Initialize class with real implementations in production.</li>
<li>Initialize class with mocks in tests.</li>
<li>Setup mocks to behave as required by each test.</li>
<li>Verify mocks.</li>
</ul>

<p>I will not talk about dependency injection in this post, but once all
components of the system expect several interfaces to run, it is worth
thinking about leveraging a DI framework to handle putting things
together.</p>

<p>With this approach, we can make any component testable except the
adapters. By their nature, our adapters perform IO. We can't reliably
test <code>HttpClientWrapper</code>. But such adapters shouldn't contain any
application logic, they should be extremely thin, simply forwarding
calls to the real implementation. It's perfectly fine to not test such
trivial code.</p>

<h3>Seams</h3>

<p>Depending on the language, we can have several other ways to inject
mocks. In C++, for example, we can do it at compile-time, at link-time,
or at run-time.</p>

<p>At compile-time, we can use a template parameter as the <q>interface</q>,
have the production version of the code instantiate it with one concrete
implementation and have the tests instantiate it with a mock:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">TImpl</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Example</span>
<span class="p">{</span>
<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">TImpl</span><span class="w"> </span><span class="n">impl</span><span class="p">;</span>

<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Do</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">impl</span><span class="p">.</span><span class="n">Do</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span><span class="w"> </span><span class="nc">ConcreteImpl</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Do</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Concrete implementation</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span><span class="w"> </span><span class="nc">MockImpl</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Do</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Mock implementation</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="c1">// ...</span>

<span class="n">Example</span><span class="o">&lt;</span><span class="n">ConcreteImpl</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ex</span><span class="p">;</span>
</pre></div>

<p>At link-time, we can link against the concrete implementations in
production and against mock implementations in tests:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Example</span>
<span class="p">{</span>
<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">Impl</span><span class="w"> </span><span class="n">impl</span><span class="p">;</span>

<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Do</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">impl</span><span class="p">.</span><span class="n">Do</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="c1">// In concrete implementation file:</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Impl</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Do</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Concrete implementation</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="c1">// In mock implementation file:</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Impl</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Do</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Mock implementation</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>At run-time, we can do something similar to our C# example above. There
are pros and cons with each approach. The run-time approach is what most
languages do, so easy to understand, though it adds more overhead. The
link-time approach is lean, but could end up being confusing: we have to
check makefiles to understand which code ends up in the binary and which
code doesn't. The compile-time approach makes the code uglier, and
requires making implementation public.</p>

<h2>Test The Public Interface</h2>

<p>This one I did mention in my previous blog post to. The key point here
is that, while test frameworks usually provide various unnatural ways to
access an object's internals, tests should focus on the public members.</p>

<p>The public members define the <q>contract</q> that a class provides. Tests
should ensure the contract is respected and not worry about the
implementation. With this approach, the implementation can easily be
refactored and we know things still work as expected as long as all
tests pass. On the other hand, if we have tests that cover various
implementation details, they might break if we move things around, even
though the class still behaves correctly. In general, having to update
tests whenever we make tweaks to the implementation is not ideal.</p>

<p>The other way to look at it is that if we have some code deep in the
implementation that can't be reached through the public members, then
it is likely dead code.</p>

<h2>Summary</h2>

<ul>
<li>Unit tests should run as part of continuous integration, otherwise
they aren't really useful.</li>
<li>Unit tests have to be 100% reliable. We achieve this by isolating IO
and mocking it in tests.</li>
<li>Testability recipe:

<ul>
<li>Code against interfaces, declare interfaces if none are
available</li>
<li>Use thin adapters to make any concrete implementation compatible
with any interface</li>
<li>Use concrete implementations in production and mocks in tests</li>
</ul></li>
<li>In some languages there are multiple seams where we can inject
mocks. In C++ we can do it at compile-time, at link-time, and at
run-time. Each has its pros and cons.</li>
<li>Test the public interface not the implementation.</li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>Moq is my favorite C# mocking library:
<a href="https://github.com/moq/moq4">https://github.com/moq/moq4</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Mon, 18 Nov 2019 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/10/16/programming-with-types-rtm.html</link>
      <guid>https://vladris.com/blog/2019/10/16/programming-with-types-rtm.html</guid>
      <title><![CDATA[Programming with Types RTM]]></title>
      <description><![CDATA[<h1>Programming with Types RTM</h1>

<p><a href="https://www.manning.com/books/programming-with-types">Programming with
Types</a> is going to
the printer today and should be available as a print books in a couple
of weeks. I figured I'll write a blog post about writing the book for
the occasion. I wrote in a <a href="https://vladris.com/blog/2019/04/28/programming-with-types.html">previous
post</a>
how the book came to be, but didn't really cover the implementation
details.</p>

<h2>Prototype</h2>

<p>I started writing the book before even thinking about publishing. The
best way I can put it is I felt I had a book in me. I learned a lot of
material during the past few years and I wanted to synthesize it in book
form, hopefully useful to others. I created a repository on GitHub,
outlined the topics I wanted to cover, and for a few weeks I spent a few
minutes every morning over coffee filling in some of the sections. As a
fun fact, the original title of the book was <em>Practical Types</em>. This was
August 2018.</p>

<h2>Pitch</h2>

<p>In September, when I realized I am indeed writing a book, I figured I
should pitch it to publishers. No harm in trying. I reached out to
O'Reilly and Manning. O'Reilly promptly dismissed my proposal. Manning
put me in touch with a publisher and we scheduled a couple of calls to
discuss some of the details.</p>

<p>I got some invaluable feedback even from those initial calls -
suggestions on how to improve the table of contents, how to make the
book more accessible to readers, how to split topics up into chapters
based on the difficulty of the topic and so on. After those initial
calls, I was fortunate to get a contract.</p>

<h2>Contract</h2>

<p>The most important part of the contract is the manuscript delivery.
There are 3 key milestones, each 4 months apart. The milestones were:</p>

<ul>
<li>Deliver a third of the manuscript no later than February 2019.</li>
<li>Deliver two thirds of the manuscript no later than June 2019.</li>
<li>Deliver the complete draft of the manuscript no later than October
2019.</li>
</ul>

<p>I got paid an advance delivered in two batches: the first half upon
delivery of the first third of the manuscript, the second half upon
delivery of the complete draft. I will also be getting a percentage of
sales of the book. The way advances work, the book needs to sell enough
to cover the advance before I will receive any more royalties. I will
pause here to say that I don't expect to get rich off of this book.
Another fun fact I learned is that most books don't even recover the
advance, so if you ever want to write a book simply for the money, you
might want to reconsider.</p>

<h2>Training</h2>

<p>After the paperwork was signed, I was assigned a developmental editor
and the first thing we did was a new author training where I was
introduced to the Manning method of writing books. Since Manning has
been publishing high quality technical books for many years, they have a
set of best practices authors are encouraged to follow. These include
things like starting with a concrete example then generalizing to the
abstract, using figures to better explain things, tracking the
prerequisites of each chapter and making sure there is a smooth
progression and so on. These trainings were delivered by my editor over
a few Skype calls.</p>

<h2>Feedback Loop</h2>

<p>Throughout the writing stage, I worked closely with two editors. After
completing a draft of each chapter, I would upload it and get the
initial round of feedback from them. The developmental editor would make
sure my writing is up to par and the text makes sense; the technical
developmental editor would keep me honest for the technical aspects of
the book, and make sure I didn't mess anything up there.</p>

<p>With each milestone (1/3, 2/3, 3/3 of the book), Manning also conducted
an external review with around 20 other volunteers who would go over the
manuscript and provide feedback. When the external feedback came in, we
analyzed it for trends to identify areas of improvement - for example,
if multiple people were saying a particular section is hard to grok, it
was clear it needed improvement.</p>

<p>As the book was nearing completion, I also got a reviewer for the code
samples. He made sure all the code makes sense, compiles, and the GitHub
version matches the book version.</p>

<p>Writing a book is definitely a team effort. Without all the great
feedback I received it would've been a pretty crappy book. Many thanks
to Michael Stephens, Elesha Hyde, Mike Shepard, German Gonzales, and all
the other great folks at Manning for all their help. I'm also grateful
to all the external reviewers for their time.</p>

<p>I learned that the first chapter is the one that usually requires the
most refactoring, which was definitely true in my case.</p>

<h2>Writing</h2>

<p>Because I started with a list of topics I wanted to cover and had a
general idea of what to write in each chapter, things went pretty
smoothly. I was able to write a chapter in a weekend so I was ahead of
schedule most of the time.</p>

<p>Turns out that writing a chapter is not the hard part, the grind comes
when you have to edit, re-edit, and incorporate all the rounds of
feedback. The editing part is much less creative than starting from a
blank page, but is equally if not more important.</p>

<p>I completed the draft mid-May and incorporated the last round of
external feedback by July. Beyond the chapters, there is also a Front
Matter, inside covers, and appendices, which I worked on in July/August.</p>

<p>All in all it took about a year from when I started outlining the book
on GitHub to having the final version ready to go to production.</p>

<h2>Production</h2>

<p>From then on, the book goes to production and another set of people goes
over the spelling, layout, indexing and so on. At this stage, my
responsibility was mostly to review changes and suggest minor updates.</p>

<p>Last week I received the final PDF version of how the book will look
like in print, and today I was notified it is being sent to the printer.</p>

<p>Writing the book was a great experience and I got the chance to work
with some wonderful people. I hope the final product is a good book
which leads to better software.</p>
]]></description>
      <pubDate>Wed, 16 Oct 2019 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/09/07/higher-kinded-types-monads.html</link>
      <guid>https://vladris.com/blog/2019/09/07/higher-kinded-types-monads.html</guid>
      <title><![CDATA[Higher Kinded Types: Monads]]></title>
      <description><![CDATA[<h1>Higher Kinded Types: Monads</h1>

<p>This blog post is an excerpt from my book, <a href="https://www.manning.com/books/programming-with-types">Programming with
Types</a>. The code
samples are in TypeScript. If you enjoy the article, you can use the
discount code <strong>vlri40</strong> for a 40% discount on the book.</p>

<p>Make sure to read the previous post first, <a href="https://vladris.com/blog/2019/09/06/higher-kinded-types-functors.html">Higher Kinded Types:
Functors</a>.</p>

<h2>Monads</h2>

<p>You have probably heard the term <em>monad</em>, as it's been getting a lot of
attention lately. Monads are making their way into mainstream
programming, so you should know one when you see it. Building on the
previous blog post, in this post we will explain what a monad is and how
it is useful. We'll start with a few examples and then look at the
general definition.</p>

<h2>Result or Error</h2>

<p>In the previous post, we had a <code>readNumber()</code> function that returned
<code>number | undefined</code>. We used functors to sequence processing with
<code>square()</code> and <code>stringify()</code>, so that if <code>readNumber()</code> returns
<code>undefined</code>, no processing happens, and the <code>undefined</code> is propagated
through the pipeline.</p>

<p>This type of sequencing works with functors as long as only the first
function - in this case, <code>readNumber()</code> - can return an error. But what
happens if any of the functions we want to chain can error out? Let's
say that we want to open a file, read its content as a <code>string</code>, and
then deserialize that string into a <code>Cat</code> object.</p>

<p>We have an <code>openFile()</code> function that returns an <code>Error</code> or a
<code>FileHandle</code>. Errors can occur if the file doesn't exist, if it is
locked by another process, or if the user doesn't have permission to
open it. If the operation succeeds, we get back a handle to the file.</p>

<p>We have a <code>readFile()</code> function that takes a <code>FileHandle</code> and returns
ether an <code>Error</code> or a <code>string</code>. Errors can occur if the file can't be
read, perhaps due to being too large to fit in memory. If the file can
be read, we get back a <code>string</code>.</p>

<p>Finally, <code>deserializeCat()</code> function takes a <code>string</code> and returns an
<code>Error</code> or a <code>Cat</code> instance. Errors can occur if the string can't be
deserialized into a <code>Cat</code> object, perhaps due to missing properties.</p>

<p>All these functions follow the <q>return result or error</q> pattern, which
suggests returning either a valid result or an error from a function,
but not both. The return type will be an <code>Either&lt;Error, ...&gt;</code>:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">openFile</span><span class="p">(</span>
<span class="w">    </span><span class="nx">path</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="nx">FileHandle</span><span class="o">&gt;</span><span class="p">;</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">readFile</span><span class="p">(</span>
<span class="w">    </span><span class="nx">handle</span><span class="o">:</span><span class="w"> </span><span class="kt">FileHandle</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="o">&gt;</span><span class="p">;</span>

<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">deserializeCat</span><span class="p">(</span>
<span class="w">    </span><span class="nx">serializedCat</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="nx">Cat</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>We are omitting the implementations, as they are not important. Let's
also quickly see the implementation of <code>Either</code>:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">TLeft</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">TRight</span><span class="p">;</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="nx">left</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="p">;</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">TLeft</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">TRight</span><span class="p">,</span><span class="w"> </span><span class="nx">left</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">left</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">isLeft</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">left</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">getLeft</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">TLeft</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">isLeft</span><span class="p">())</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">();</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="o">&gt;</span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">isRight</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">left</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">getRight</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">TRight</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">isRight</span><span class="p">())</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="ne">Error</span><span class="p">();</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">TRight</span><span class="o">&gt;</span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="nx">makeLeft</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">TLeft</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span><span class="w"> </span><span class="kc">true</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="nx">makeRight</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">TRight</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span><span class="w"> </span><span class="kc">false</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>The type wraps a value of either <code>TLeft</code> or <code>TRight</code> and a flag to keep
track of that type is used. It has a private constructor, as we need to
make sure that the value and boolean flag are in sync. Attempting to get
a <code>TLeft</code> when we have a <code>TRight</code>, or vice versa, throws an error. The
factory functions call the constructor and ensure that the boolean flag
is consistent with the value.</p>

<p>Now let's see how we could chain these functions together into a
<code>readCatFromFile()</code> function that takes a file path as an argument and
returns an <code>Error</code> if anything went wrong along the way, or a <code>Cat</code>
instance:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">readCatFromFile</span><span class="p">(</span><span class="nx">path</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="nx">Cat</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">handle</span><span class="o">:</span><span class="w"> </span><span class="kt">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="nx">FileHandle</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">openFile</span><span class="p">(</span><span class="nx">path</span><span class="p">);</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">handle</span><span class="p">.</span><span class="nx">isLeft</span><span class="p">())</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">Either</span><span class="p">.</span><span class="nx">makeLeft</span><span class="p">(</span><span class="nx">handle</span><span class="p">.</span><span class="nx">getLeft</span><span class="p">());</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">content</span><span class="o">:</span><span class="w"> </span><span class="kt">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">readFile</span><span class="p">(</span><span class="nx">handle</span><span class="p">.</span><span class="nx">getRight</span><span class="p">());</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">content</span><span class="p">.</span><span class="nx">isLeft</span><span class="p">())</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">Either</span><span class="p">.</span><span class="nx">makeLeft</span><span class="p">(</span><span class="nx">content</span><span class="p">.</span><span class="nx">getLeft</span><span class="p">());</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">deserializeCat</span><span class="p">(</span><span class="nx">content</span><span class="p">.</span><span class="nx">getRight</span><span class="p">());</span>
<span class="p">}</span>
</pre></div>

<p>This function is very similar to the first implementation of <code>process()</code>
in the previous blog post. There, we provided an updated implementation
that removed all the branching and error checking from the function and
delegated those tasks to <code>map()</code>. Let's see what a <code>map()</code> for
<code>Either&lt;TLeft, TRight&gt;</code> would look like. We will follow the convention
<q>Right is right; left is error</q>, which means that <code>TLeft</code> contains an
error, so <code>map()</code> will just propagate it. <code>map()</code> will apply a given
function only if the <code>Either</code> contains a <code>TRight</code>:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">Either</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="p">,</span><span class="w"> </span><span class="nx">URight</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">Either</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">TRight</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">URight</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">URight</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">isLeft</span><span class="p">())</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">Either</span><span class="p">.</span><span class="nx">makeLeft</span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">getLeft</span><span class="p">());</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">Either</span><span class="p">.</span><span class="nx">makeRight</span><span class="p">(</span><span class="nx">func</span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">getRight</span><span class="p">()));</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>There is a problem with using <code>map()</code>, though: the types of the
functions it expects as argument is incompatible with the functions we
are using. With <code>map()</code>, after we call <code>openFile()</code> and get back an
<code>Either&lt;Error, FileHandle&gt;</code>, we would need a function
<code>(value: FileHandle) =&gt; string</code> to read its content. That function can't
itself return an <code>Error</code>, like <code>square()</code> or <code>stringify()</code>. But in our
case, <code>readFile()</code> itself can fail, so it doesn't return <code>string</code>, it
returns <code>Either&lt;Error, string&gt;</code>. If we attempt to use it in our
<code>readCatFromFile()</code>, we get a compilation error:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">readCatFromFile</span><span class="p">(</span><span class="nx">path</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="nx">Cat</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">handle</span><span class="o">:</span><span class="w"> </span><span class="kt">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="nx">FileHandle</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">openFile</span><span class="p">(</span><span class="nx">path</span><span class="p">);</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">content</span><span class="o">:</span><span class="w"> </span><span class="kt">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">Either</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">handle</span><span class="p">,</span><span class="w"> </span><span class="nx">readFile</span><span class="p">);</span>

<span class="w">    </span><span class="cm">/* ... */</span>
<span class="p">}</span>
</pre></div>

<p>This fails to compile due to a type mismatch. The error message we get
is</p>

<blockquote>
<p><code>Type 'Either&lt;Error, Either&lt;Error, string&gt;&gt;' is not assignable to type 'Either&lt;Error, string&gt;'.</code></p>
</blockquote>

<p>Our functor falls short here. Functors can propagate an initial error
through the processing pipeline, but if every step in the pipeline can
fail, functors no longer work. In the following figure, the black square
represents an <code>Error</code>, and the white and black circles represent two
types, such as <code>FileHandle</code> and <code>string</code>.</p>

<p><img src="https://vladris.com/blog/2019/09/07/bind1.png" alt="image"/></p>

<p>We can't use a functor in this case because the functor is defined to
map a function from a white circle to a black circle. Unfortunately, our
function returns a type already wrapped in an <code>Either</code> (an
<code>Either&lt;black square, black circle&gt;</code>). We need an alternative to <code>map()</code>
that can deal with this type of function.</p>

<p><code>map()</code> from <code>Either&lt;Error, FileHandle&gt;</code> would need a function from
<code>FileHandle</code> to <code>string</code> to produce an <code>Either&lt;Error, string&gt;</code>. Our
<code>readFile()</code> function, on the other hand, is from <code>FileHandle</code> to
<code>Either&lt;Error, string&gt;</code>.</p>

<p>This problem is easy to fix. We need a function similar to <code>map()</code> that
goes from <code>T</code> to <code>Either&lt;Error, U&gt;</code>. The standard name for such a
function is <code>bind()</code>:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">Either</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">bind</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="p">,</span><span class="w"> </span><span class="nx">URight</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">Either</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">TRight</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">TRight</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">URight</span><span class="o">&gt;</span>
<span class="w">        </span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="nx">TLeft</span><span class="p">,</span><span class="w"> </span><span class="nx">URight</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">isLeft</span><span class="p">())</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nx">Either</span><span class="p">.</span><span class="nx">makeLeft</span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">getLeft</span><span class="p">());</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">getRight</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>func()</code> has a different type from the <code>func()</code> in <code>map()</code>. We can
simply return the result of <code>func()</code>, as it has the same type as the
result of <code>bind()</code>.</p>

<p>As we can see, the implementation is even simpler than the one for
<code>map()</code>: after we unpack the value, we simply return the result of
applying <code>func()</code> to it. Let's use <code>bind()</code> to implement our
<code>readCatFromFile()</code> function and get the desired branchless error
propagation behavior:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">readCatFromFile</span><span class="p">(</span><span class="nx">path</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="nx">Cat</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">handle</span><span class="o">:</span><span class="w"> </span><span class="kt">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="nx">FileHandle</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">openFile</span><span class="p">(</span><span class="nx">path</span><span class="p">)</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">content</span><span class="o">:</span><span class="w"> </span><span class="kt">Either</span><span class="o">&lt;</span><span class="ne">Error</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span>
<span class="w">        </span><span class="nx">Either</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">handle</span><span class="p">,</span><span class="w"> </span><span class="nx">readFile</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">Either</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="nx">content</span><span class="p">,</span><span class="w"> </span><span class="nx">deserializeCat</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Unlike the <code>map()</code> version, this code works. Applying <code>readFile()</code> to
<code>handle</code> gives us back an <code>Either&lt;Error, string&gt;</code>. <code>deserializeCat()</code>
has the same return type as <code>readCatFromFile()</code>, so we simply return the
result of <code>bind()</code>.</p>

<p>This version seamlessly chains together <code>openFile()</code>, <code>readFile()</code>, and
<code>deserializeCat()</code> so that if any of the functions fails, the error gets
propagated as the result of <code>readCatFromFile()</code>. Again, branching is
encapsulated in the <code>bind()</code> implementation, so our processing function
is linear.</p>

<h2>Difference between map() and bind()</h2>

<p>Before moving on to define monads, let's take another simplified example
and contrast <code>map()</code> and <code>bind()</code>. We'll again use <code>Box&lt;T&gt;</code>, a generic
type that simply wraps a value of type <code>T</code>. Although this type is not
particularly useful, it is the simplest generic type we can have. We
want to focus on how <code>map()</code> and <code>bind()</code> work with values of types <code>T</code>
and <code>U</code> in some generic context, such as <code>Box&lt;T&gt;</code>, <code>Box&lt;U&gt;</code> (or <code>T[]</code>,
<code>U[]</code>; or <code>Optional&lt;T&gt;</code>, <code>Optional&lt;U&gt;</code>; or <code>Either&lt;Error, T&gt;</code>,
<code>Either&lt;Error, U&gt;</code> etc.).</p>

<p>For a <code>Box&lt;T&gt;</code>, a functor (<code>map()</code>) takes a <code>Box&lt;T&gt;</code> and a function from
<code>T</code> to <code>U</code> and returns a <code>Box&lt;U&gt;</code>. The problem is that we have scenarios
in which our functions are directly from <code>T</code> to <code>Box&lt;U&gt;</code>. This is what
<code>bind()</code> is for. <code>bind()</code> takes a <code>Box&lt;T&gt;</code> and a function from <code>T</code> to
<code>Box&lt;U&gt;</code> and returns the result of applying the function to the <code>T</code>
inside <code>Box&lt;T&gt;</code>.</p>

<p><img src="https://vladris.com/blog/2019/09/07/bind2.png" alt="image"/></p>

<p>If we have a function <code>stringify()</code> that takes a <code>number</code> and returns
its <code>string</code> representation, we can <code>map()</code> it on a <code>Box&lt;number&gt;</code> and
get back a <code>Box&lt;string&gt;</code>:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">Box</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">box</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">value</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">stringify</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">value</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span>
<span class="p">}</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">s</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span>
<span class="w">    </span><span class="o">=</span><span class="w"> </span><span class="nx">Box</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="mf">42</span><span class="p">),</span><span class="w"> </span><span class="nx">stringify</span><span class="p">);</span>
</pre></div>

<p>If instead of <code>stringify()</code>, which goes from <code>number</code> to <code>string</code>, we
have a <code>boxify()</code> function that goes from <code>number</code> directly to
<code>Box&lt;string&gt;</code>[, ]{.title-ref}[map()]{.title-ref}[ won't work. We'll need
]{.title-ref}[bind()]{.title-ref}` instead:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">Box</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">bind</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">box</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">value</span><span class="p">);</span><span class="w">    </span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">boxify</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="nx">value</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span>
<span class="p">}</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">b</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span>
<span class="w">    </span><span class="nx">Box</span><span class="p">.</span><span class="nx">bind</span><span class="p">(</span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="mf">42</span><span class="p">),</span><span class="w"> </span><span class="nx">boxify</span><span class="p">);</span>
</pre></div>

<p>The result of both <code>map()</code> and <code>bind()</code> is still a <code>Box&lt;string&gt;</code>. We
still go from <code>Box&lt;T&gt;</code> to <code>Box&lt;U&gt;</code>; the difference is how we get there.
In the <code>map()</code> case, we need a function from <code>T</code> to <code>U</code>. In the <code>bind()</code>
case, we need a function from <code>T</code> to <code>Box&lt;U&gt;</code>.</p>

<h2>The Monad Pattern</h2>

<p>A monad consists of <code>bind()</code> and one more, simpler function. This other
function takes a type <code>T</code> and wraps it into the generic type, such as
<code>Box&lt;T&gt;</code>, <code>T[]</code>, <code>Optional&lt;T&gt;</code>, or <code>Either&lt;Error, T&gt;</code>. This function is
usually called <code>return()</code> or <code>unit()</code>.</p>

<p>A monad allows structuring programs generically while encapsulating away
boilerplate code needed by the program logic. With monads, a sequence of
function calls can be expressed as a pipeline that abstracts away data
management, control flow, or side effects.</p>

<p>Let's look at a few examples of monads. We can start with our simple
<code>Box&lt;T&gt;</code> type and add <code>unit()</code> to it to complete the monad:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">Box</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">unit</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">bind</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">box</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">value</span><span class="p">);</span><span class="w">    </span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>unit()</code> simply calls <code>Box</code>'s constructor to wrap the given value into
an instance of <code>Box&lt;T&gt;</code>. <code>bind()</code> unpacks the value from <code>Box</code> and calls
<code>func()</code> on it.</p>

<p>The implementation is very straightforward. Let's look at the
<code>Optional&lt;T&gt;</code> monad functions:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">Optional</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">unit</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Optional</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Optional</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">bind</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">optional</span><span class="o">:</span><span class="w"> </span><span class="kt">Optional</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">Optional</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Optional</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="nx">optional</span><span class="p">.</span><span class="nx">hasValue</span><span class="p">())</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Optional</span><span class="p">();</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">optional</span><span class="p">.</span><span class="nx">getValue</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>unit()</code> takes a value of type <code>T</code> and wraps it into an <code>Optional&lt;T&gt;</code>.
If the optional is empty, <code>bind()</code> returns an empty optional of type
<code>Optional&lt;U&gt;</code>. If the optional contains a value, <code>bind()</code> return the
result of calling <code>func()</code> on it.</p>

<p>Very much as with functors, if a programming language can't express
higher kinded types, we don't have a good way to specify a <code>Monad</code>
interface. Instead, let's think of monads as a pattern:</p>

<blockquote>
<p>A monad is a generic type <code>H&lt;T&gt;</code> for which we have a function like
<code>unit()</code>, that takes a value of type <code>T</code> and returns a value of type
<code>H&lt;T&gt;</code>, and a function like <code>bind()</code> that takes a value of type <code>H&lt;T&gt;</code>
and a function from <code>T</code> to <code>H&lt;U&gt;</code>, and returns a value of type <code>H&lt;U&gt;</code>.</p>
</blockquote>

<p>Bear in mind that because most languages use this pattern, without a way
to specify an interface for the compiler to check, in many instances the
two functions, <code>unit()</code> and <code>bind()</code>, may show up under different names.
You may hear the term <em>monadic</em>, as in <strong>monadic error handling</strong>, which
means that error handling follows the monad pattern.</p>

<p>Next, we'll look at a few other examples.</p>

<h2>The Continuation Monad</h2>

<p>A promise represents the result of a computation that will happen
sometime in the future. <code>Promise&lt;T&gt;</code> is the promise of a value of type
<code>T</code>. We can schedule execution of asynchronous code by chaining
promises, using the <code>then()</code> function.</p>

<p>Let's say we have a function that determines our location on the map.
Because this function will work with the GPS, it may take longer to
finish, so we make it asynchronous. It will return a promise of type
<code>Promise&lt;Location&gt;</code>. Next, we have a function that, given a location,
will contact a ride-sharing service to get us a <code>Car</code>:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">getLocation</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">Location</span><span class="o">&gt;</span><span class="p">;</span>
<span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">hailRideshare</span><span class="p">(</span>
<span class="w">    </span><span class="nx">location</span><span class="o">:</span><span class="w"> </span><span class="kt">Location</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nb">Promise</span><span class="o">&lt;</span><span class="nx">Car</span><span class="o">&gt;</span><span class="p">;</span>

<span class="kd">let</span><span class="w"> </span><span class="nx">car</span><span class="o">:</span><span class="w"> </span><span class="kt">Promise</span><span class="o">&lt;</span><span class="nx">Car</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">getLocation</span><span class="p">().</span><span class="nx">then</span><span class="p">(</span><span class="nx">hailRideshare</span><span class="p">);</span>
</pre></div>

<p>When <code>getLocation()</code> returns, <code>hailRideshare()</code> will be invoked with its
result. This should look very familiar to you at this point. <code>then()</code> is
just how <code>Promise&lt;T&gt;</code> spells <code>bind()</code>!</p>

<p>we can also create an instantly resolved promise by using
<code>Promise.resolve()</code>. This takes a value and returns a resolved promise
containing that value, which is the <code>Promise&lt;T&gt;</code> equivalent of <code>unit()</code>.</p>

<p>Turns out chaining promises, an API available in virtually all
mainstream programming languages, is monadic. It follows the same
pattern that we saw in this section, but in a different domain. While
dealing with error propagation, our monad encapsulated checking whether
we have a value that we can continue operating on or have an error that
we should propagate. With promises, the monad encapsulates the
intricacies of scheduling and resuming execution. The pattern is the
same, though.</p>

<h2>The List Monad</h2>

<p>Another commonly used monad is the list monad. Let's look at an
implementation over sequences: a <code>divisors()</code> function that takes a
number n and returns an array containing all of its divisors except 1
and n itself.</p>

<p>This straightforward implementation starts from 2 and goes up to half of
n, and adds all numbers it finds that divide n without a remainder.
There are more efficient ways to find all divisors of a number, but
we'll stick to a simple algorithm in this case:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">divisors</span><span class="p">(</span><span class="nx">n</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">2</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mf">2</span><span class="p">;</span><span class="w"> </span><span class="nx">i</span><span class="o">++</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">n</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="nx">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Now let's say we want to take an array of numbers and return an array
containing all their divisors. We don't need to worry about dupes. One
way to do this is to provide a function that takes an array of input
numbers, applies <code>divisors()</code> to each of them, and joins the results of
all the calls to <code>divisors()</code> into a final result:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">allDivisors</span><span class="p">(</span><span class="nx">ns</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">n</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">ns</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">divisors</span><span class="p">(</span><span class="nx">n</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>It turns out that this pattern is common. Let's say that we have another
function, <code>anagrams()</code>, that generates all permutations of a string and
returns an array of strings. If we want to get the set of all anagrams
of an array of strings, we would end up implementing a very similar
function:</p>
<div class="highlight"><pre><span/><span class="kr">declare</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">anagram</span><span class="p">(</span><span class="nx">input</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[];</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">allAnagrams</span><span class="p">(</span><span class="nx">inputs</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">input</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">inputs</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">anagram</span><span class="p">(</span><span class="nx">input</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p><code>allAnagrams()</code> is very similar to <code>allDivisors()</code>.</p>

<p>Now let's see whether we can replace <code>allDivisors()</code> and <code>allAnagrams()</code>
with a generic function. This function would take an array of <code>T</code>s and a
function from <code>T</code> to an array of <code>U</code>s, and return an array of <code>U</code>s:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">bind</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">inputs</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">[],</span>
<span class="w">    </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="nx">U</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">U</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">input</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">inputs</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="nx">func</span><span class="p">(</span><span class="nx">input</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">allDivisors</span><span class="p">(</span><span class="nx">ns</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">bind</span><span class="p">(</span><span class="nx">ns</span><span class="p">,</span><span class="w"> </span><span class="nx">divisors</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">allAnagrams</span><span class="p">(</span><span class="nx">inputs</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">bind</span><span class="p">(</span><span class="nx">inputs</span><span class="p">,</span><span class="w"> </span><span class="nx">anagram</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>As you've probably guessed, this is the <code>bind()</code> implementation for the
list monad. In the case of lists, <code>bind()</code> flattens the arrays returned
by each call of the given function into a single array. While the
error-propagating monad decides whether to propagate an error or apply a
function and the continuation monad wraps scheduling, the list monad
combines a set of results (a list of lists) into a single flat list. In
this case, the box is a sequence of values.</p>

<p><img src="https://vladris.com/blog/2019/09/07/bind3.png" alt="image"/></p>

<p>The <code>unit()</code> implementation is trivial. Given a value of type <code>T</code>, it
returns a list containing just that value. This monad generalizes to all
kinds of lists: arrays, linked lists, and iterator ranges.</p>

<blockquote>
<p><strong>Category theory</strong></p>

<p>Functors and monads come from category theory, a branch of mathematics
that deals with structures consisting of objects and arrows between
these objects. With these small building blocks, we can build up
structures such as functors and monads. We won't go into its details
now; we'll just say that multiple domains, like set theory and even
type systems, can be expressed in category theory.</p>

<p>Haskell is a programming language that took a lot of inspiration from
category theory, so its syntax and standard library make it easy to
express concepts such as functors, monads, and other structures.
Haskell fully supports higher kinded types.</p>

<p>Maybe because the building blocks of category theory are so simple,
the abstractions we've been talking about are applicable across so
many domains. We just saw that monads are useful in the context of
error propagation, asynchronous code, and sequence processing.</p>

<p>Although most mainstream languages still treat monads as patterns
instead of proper constructs, they are definitely useful structures
that show up over and over in different contexts.</p>
</blockquote>

<h2>Other Monads</h2>

<p>A couple of other common monads, which are popular in functional
programming languages with pure functions (functions that don't have
side effects) and immutable data, are the state monad and the IO monad.
We'll provide only a high-level overview of these monads, but if you
decide to learn a functional programming language such as Haskell, you
will likely encounter them early in your journey.</p>

<p>The state monad encapsulates a piece of state that it passes along with
a value. This monad enables us to write pure functions that, given a
current state, produce a value and an updated state. Chaining these
together with <code>bind()</code> allows us to propagate and update state through a
pipeline without explicitly storing it in a variable, enabling purely
functional code to process and update state.</p>

<p>The IO monad encapsulates side effects. It allows us to implement pure
functions that can still read user input or write to a file or terminal
because the impure behavior is removed from the function and wrapped in
the IO monad.</p>
]]></description>
      <pubDate>Sat, 07 Sep 2019 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/09/06/higher-kinded-types-functors.html</link>
      <guid>https://vladris.com/blog/2019/09/06/higher-kinded-types-functors.html</guid>
      <title><![CDATA[Higher Kinded Types: Functors]]></title>
      <description><![CDATA[<h1>Higher Kinded Types: Functors</h1>

<p>This blog post is an excerpt from my book, <a href="https://www.manning.com/books/programming-with-types">Programming with
Types</a>. The code
samples are in TypeScript. If you enjoy the article, you can use the
discount code <strong>vlri40</strong> for a 40% discount on the book.</p>

<h2>An Even More General Map</h2>

<p>In the <a href="https://vladris.com/blog/2019/08/10/common-algorithms.html">previous
post</a> we saw
a generic <code>map()</code> implementation working on iterators. Iterators
abstract data structure traversal, so <code>map()</code> can apply a function to
elements in any data structure.</p>

<p><img src="https://vladris.com/blog/2019/09/06/map1.png" alt="image"/></p>

<p>In the figure, <code>map()</code> takes an iterator over a sequence, in this case a
list of circles, and a function which transforms a circle. <code>map()</code>
applies the function to each element in the sequence, and produces a new
sequence with the transformed elements.</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="o">*</span><span class="w"> </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">iter</span><span class="o">:</span><span class="w"> </span><span class="kt">Iterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">item</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">iter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">yield</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This implementation works on iterators, but we should be able to apply a
function of the form <code>(item: T) =&gt; U</code> to other types too. Let's take,
as an example, an <code>Optional&lt;T&gt;</code> type:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">Optional</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">assigned</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="p">;</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">value?</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">assigned</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">assigned</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">hasValue</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="kt">boolean</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">assigned</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">getValue</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="nx">T</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">assigned</span><span class="p">)</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="ne">Error</span><span class="p">();</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>It feels natural to be able to map a function <code>(value: T) =&gt; U</code> over an
<code>Optional&lt;T&gt;</code>. If the optional contains a value of type <code>T</code>, mapping the
function over it should return an <code>Optional&lt;U&gt;</code> containing the result of
applying the function. On the other hand, if the optional doesn't
contain a value, mapping would result in an empty <code>Optional&lt;U&gt;</code>.</p>

<p><img src="https://vladris.com/blog/2019/09/06/map2.png" alt="image"/></p>

<p>Let's sketch out an implementation for this. We'll put this function
in a namespace. Since TypeScript doesn't support function overloading,
in order to have multiple functions with the same name, we need this so
the compiler can determine which function we are calling. Here's the
<code>Optional&lt;T&gt;</code> <code>map()</code> implementation:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">Optional</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">optional</span><span class="o">:</span><span class="w"> </span><span class="kt">Optional</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Optional</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">optional</span><span class="p">.</span><span class="nx">hasValue</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Optional</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="p">(</span><span class="nx">optional</span><span class="p">.</span><span class="nx">getValue</span><span class="p">()));</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Optional</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>export</code> simply makes the function visible outside the namespace. If the
optional has a value, we extract it, pass it to <code>func()</code>, and use its
result to initialize an <code>Optional&lt;U&gt;</code>. If the optional is empty, we
create a new empty <code>Optional&lt;U&gt;</code>.</p>

<p>We can do something very similar with the TypeScript sum type <code>T</code> or
<code>undefined</code>. The <code>Optional&lt;T&gt;</code> we just saw is a DIY version of such a
type that works even in languages which don't support sum types
natively, but TypeScript does. Let's see how we can map over a
<q>native</q> optional type <code>T | undefined</code>.</p>

<p>Mapping a function <code>(value: T) =&gt; U</code> over <code>T | undefined</code> should apply
the function and return its result if we have a value of type <code>T</code>, or
return <code>undefined</code> if we start with <code>undefined</code>:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">SumType</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">U</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>These types can't be iterated over, but it still makes sense for a
<code>map()</code> function to exist for them. Let's define another simple generic
type, <code>Box&lt;T&gt;</code>. This type simply wraps a value of type <code>T</code>:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">;</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Can we map a function <code>(value: T) =&gt; U</code> over this type? We can. As you
might have guessed, <code>map()</code> for <code>Box&lt;T&gt;</code> would return a <code>Box&lt;U&gt;</code>: it
will take the value <code>T</code> out of <code>Box&lt;T&gt;</code>, apply the function to it, and
put the result back into a <code>Box&lt;U&gt;</code>.</p>

<p><img src="https://vladris.com/blog/2019/09/06/map3.png" alt="image"/></p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">Box</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">box</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">value</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>There are many generic types over which we can map functions. Why is
this useful? It's useful because <code>map()</code>, just like iterators, provides
another way to decouple types which store data from functions which
operate on that data.</p>

<h2>Processing Results or Propagating Errors</h2>

<p>As a concrete example, let's take a couple of functions which process a
numerical value. We'll implement a simple <code>square()</code>, a function which
takes a number as an argument and returns its square. We'll also
implement <code>stringify()</code>, a function which takes a number as an argument
and returns its string representation:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">square</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">**</span><span class="w"> </span><span class="mf">2</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">stringify</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">value</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>Now let's say we have a function <code>readNumber()</code>, which reads a numeric
value from a file. Since we are dealing with input, we might run into
some problems: what if the file doesn't exist or can't be opened? In
that case, <code>readNumber()</code> will return <code>undefined</code>. We won't look at the
implementation of this function, the important thing for our example is
its return type:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">readNumber</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="cm">/* Implementation omitted */</span>
<span class="p">}</span>
</pre></div>

<p>If we want to read a number and process it by applying <code>square()</code> to it
first, then <code>stringify()</code>, we need to ensure we actually have a
numerical value as opposed to <code>undefined</code>. A possible implementation is
to convert from <code>number | undefined</code> to just <code>number</code> using <code>if</code>
statements wherever needed:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">process</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">readNumber</span><span class="p">();</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">stringify</span><span class="p">(</span><span class="nx">square</span><span class="p">(</span><span class="nx">value</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>We have two functions that operate on numbers, but since our input can
also be <code>undefined</code>, we need to explicitly handle that case. This is not
particularly bad, but in general the less branching our code has, the
less complex it is. It is easier to understand, to maintain, and there
are less opportunities for bugs. Another way to look at this is that
<code>process()</code> itself simply propagates <code>undefined</code>, it doesn't do
anything useful with it. It would be better if we can keep <code>process()</code>
responsible for processing, and let someone else handle error cases. How
can we do this? With the <code>map()</code> we implemented for sum types:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nx">SumType</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">U</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">process</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">readNumber</span><span class="p">();</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">squaredValue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">SumType</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span><span class="w"> </span><span class="nx">square</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">SumType</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">squaredValue</span><span class="p">,</span><span class="w"> </span><span class="nx">stringify</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Instead of explicitly checking for <code>undefined</code>, we call <code>map()</code> to apply
<code>square()</code> on the value. If it is <code>undefined</code>, <code>map()</code> will give us back
<code>undefined</code>. Just like with <code>square()</code>, we <code>map()</code> our <code>stringify()</code>
function on the <code>squaredValue</code>. If it is <code>undefined</code>, <code>map()</code> will
return <code>undefined</code>.</p>

<p>Now our <code>process()</code> implementation has no branching -- the
responsibility of unpacking <code>number | undefined</code> into a <code>number</code> and
checking for <code>undefined</code> is handled by <code>map()</code>. <code>map()</code> is generic and
can be used across many other types (like <code>string | undefined</code>) and in
many other processing functions.</p>

<p>In our case, since <code>square()</code> is guaranteed to return a <code>number</code>, we can
create a small lambda which chains <code>square()</code> and <code>stringify()</code>, and
pass that to <code>map()</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">process</span><span class="p">()</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">readNumber</span><span class="p">();</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">SumType</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span>
<span class="w">        </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">stringify</span><span class="p">(</span><span class="nx">square</span><span class="p">(</span><span class="nx">value</span><span class="p">)));</span>
<span class="p">}</span>
</pre></div>

<p>This is a functional implementation of <code>process()</code>, in which the error
propagation is delegated to <code>map()</code>. We'll talk more about error
handling in a later blog post, when we will discuss monads. For now,
let's look at another application of <code>map()</code>.</p>

<h2>Mix-and-match Function Application</h2>

<p>Without the <code>map()</code> family of functions, if we have a <code>square()</code>
function which squares a <code>number</code>, we would have to implement some
additional logic to get a <code>number</code> from a <code>number | undefined</code> sum type.
Similarly, we would have to implement some additional logic to get a
value from a <code>Box&lt;number&gt;</code>, and package it back in a <code>Box&lt;number&gt;</code>:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">squareSumType</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span>
<span class="w">    </span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">square</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">squareBox</span><span class="p">(</span><span class="nx">box</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="kt">number</span><span class="o">&gt;</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="kt">number</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="nx">square</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">value</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>So far this isn't too bad. But what if we want something similar with
<code>stringify()</code>? We'll again end up writing two functions which look a
lot like the previous ones:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">stringifySumType</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span>
<span class="w">    </span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="kc">undefined</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="kc">undefined</span><span class="p">;</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">stringify</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">stringifyBox</span><span class="p">(</span><span class="nx">box</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="kt">number</span><span class="o">&gt;</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">value</span><span class="p">))</span>
<span class="p">}</span>
</pre></div>

<p>This starts to look like duplicate code, which is never good. If we have
<code>map()</code> functions available for <code>number | undefined</code> and <code>Box</code>, they
provide the abstraction to remove the duplicate code. We can pass either
<code>square()</code> or <code>stringify()</code> to either <code>SumType.map()</code> or to <code>Box.map()</code>,
no additional code needed:</p>
<div class="highlight"><pre><span/><span class="kd">let</span><span class="w"> </span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kc">undefined</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1</span><span class="p">;</span>
<span class="kd">let</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="kt">Box</span><span class="o">&lt;</span><span class="kt">number</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="mf">42</span><span class="p">);</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">SumType</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">stringify</span><span class="p">));</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">stringify</span><span class="p">));</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">SumType</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">square</span><span class="p">));</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">y</span><span class="p">,</span><span class="w"> </span><span class="nx">square</span><span class="p">));</span>
</pre></div>

<p>Now let's define this family of <code>map()</code> functions.</p>

<h2>Functors and Higher Kinded Types</h2>

<p>What we just talked about in this section are <em>functors</em>.</p>

<p>A functor is a generalization of functions that perform mapping
operations. For any generic type like <code>Box&lt;T&gt;</code>, a <code>map()</code> operation
which takes a <code>Box&lt;T&gt;</code> and a function from <code>T</code> to <code>U</code> and produces a
<code>Box&lt;U&gt;</code> is a functor.</p>

<p><img src="https://vladris.com/blog/2019/09/06/map4.png" alt="image"/></p>

<p>In the figure we have a generic type <code>H</code> which contains 0, 1, or more
values of some type <code>T</code>, and a function from <code>T</code> to <code>U</code>. In this case
<code>T</code> is an empty circle and <code>U</code> is a full circle. The <code>map()</code> functor
unpacks the <code>T</code> or <code>T</code>s from the <code>H&lt;T&gt;</code> instance, applies the function,
then places the result back into an <code>H&lt;U&gt;</code>.</p>

<p>Functors are extremely powerful concepts, but most mainstream languages
do not have a good way to express them. That's because the general
definition of a functor relies on <em>higher kinded types</em>.</p>

<p>A generic type is a type which has a type parameter, for example a
generic type <code>T</code>, or a type like <code>Box&lt;T&gt;</code>, have a type parameter <code>T</code>. A
higher kinded type, just like a higher-order function, represents a type
parameter with another type parameter. For example, <code>T&lt;U&gt;</code> or
<code>Box&lt;T&lt;U&gt;&gt;</code>, have a type parameter <code>T</code> which, in turn, has a type
parameter <code>U</code>.</p>

<p>Since we don't have a good way to express higher kinded types in
TypeScript, C#, or Java, we can't define a construct using the type
system to express a functor. Languages like Haskell and Idris, with more
powerful type systems, make these definitions possible. In our case
though, since we can't enforce this capability through the type system,
we can think of it more as a pattern.</p>

<p>We can say a functor is any type <code>H</code> with a type parameter <code>T</code> (<code>H&lt;T&gt;</code>)
for which we have a function <code>map()</code> which takes an argument of type
<code>H&lt;T&gt;</code>, and a function from <code>T</code> to <code>U</code>, and returns a value of type
<code>H&lt;U&gt;</code>.</p>

<p>Alternately, if we want to be more object-oriented, we can make <code>map()</code>
a member function and say <code>H&lt;T&gt;</code> is a functor if it has a method <code>map()</code>
which takes a function from <code>T</code> to <code>U</code> and returns a value of type
<code>H&lt;U&gt;</code>.</p>

<p>To see exactly where the type system is lacking, we can try to sketch
out an interface for it. Let's call this interface <code>Functor</code> and have
it declare <code>map()</code>:</p>
<div class="highlight"><pre><span/><span class="kd">interface</span><span class="w"> </span><span class="nx">Functor</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Functor</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>We can update <code>Box&lt;T&gt;</code> to implement this interface:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">implements</span><span class="w"> </span><span class="nx">Functor</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">;</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="nx">func</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This code compiles, the only problem is that it isn't specific enough.
Calling <code>map()</code> on <code>Box&lt;T&gt;</code> returns an instance of type <code>Box&lt;U&gt;</code>. But if
we work with <code>Functor</code> interfaces, we see that the <code>map()</code> declaration
specifies it returns a <code>Functor&lt;U&gt;</code>, not a <code>Box&lt;U&gt;</code>. This isn't
specific enough. We need a way to specify, when we declare the
interface, exactly what the return type of <code>map()</code> will be (in this case
<code>Box&lt;U&gt;</code>).</p>

<p>We would like to be able to say <q>this interface will be implemented by
a type <code>H</code> with a type argument <code>T</code></q>. The following code shows how this
declaration would look like if TypeScript supported higher kinded types.
It obviously doesn't compile:</p>
<div class="highlight"><pre><span/><span class="kd">interface</span><span class="w"> </span><span class="nx">Functor</span><span class="o">&lt;</span><span class="nx">H</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">H</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">class</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">implements</span><span class="w"> </span><span class="nx">Functor</span><span class="o">&lt;</span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">;</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">Box</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">Box</span><span class="p">(</span><span class="nx">func</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Lacking this, let's just think of our <code>map()</code> implementations as a
pattern for applying functions to generic types, or <q>values in some
box</q>.</p>

<h2>Functors for Functions</h2>

<p>Note that we also have functors over functions. Given a function with
any number of arguments that returns a value of type <code>T</code>, we can map a
function which takes a <code>T</code> and produces a <code>U</code> over it, and end up with a
function which takes the same inputs as the original function and
returns a value of type <code>U</code>. <code>map()</code> in this case is simply function
composition.</p>

<p><img src="https://vladris.com/blog/2019/09/06/map5.png" alt="image"/></p>

<p>Mapping a function over another function composes the two functions. The
result is a function which takes the same arguments as the original
function and returns a value of the second function's return type. The
two functions need to be compatible -- the second function must expect
an argument of the same type as the one returned by the original
function.</p>

<p>As an example, let's take a function which takes two arguments of type
<code>T</code>, and produces a value of type <code>T</code> and implement its corresponding
<code>map()</code>. This will return a function which takes two arguments of type
<code>T</code> and returns a value of type <code>U</code>:</p>
<div class="highlight"><pre><span/><span class="nx">namespace</span><span class="w"> </span><span class="nb">Function</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">export</span><span class="w"> </span><span class="kd">function</span><span class="w"> </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">T</span><span class="p">,</span><span class="w"> </span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">        </span><span class="nx">f</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">arg1</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">arg2</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">T</span><span class="p">,</span>
<span class="w">        </span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">arg1</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">arg2</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="nx">arg1</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">arg2</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">f</span><span class="p">(</span><span class="nx">arg1</span><span class="p">,</span><span class="w"> </span><span class="nx">arg2</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>map()</code> takes a function <code>(T, T) =&gt; T</code>, and a function <code>T =&gt; U</code> to map
over it. It returns a lambda function <code>(T, T) =&gt; U</code>.</p>

<p>Let's map <code>stringify()</code> over a function <code>add()</code>, which takes two
numbers and returns their sum. The result is a function which takes two
numbers and returns a string, the stringified result of adding the two
numbers:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">add</span><span class="p">(</span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">stringify</span><span class="p">(</span><span class="nx">value</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">value</span><span class="p">.</span><span class="nx">toString</span><span class="p">();</span>
<span class="p">}</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">Function</span><span class="p">.</span><span class="nx">map</span><span class="p">(</span><span class="nx">add</span><span class="p">,</span><span class="w"> </span><span class="nx">stringify</span><span class="p">)(</span><span class="mf">40</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">);</span>
</pre></div>

<h2>Summary</h2>

<ul>
<li><code>map()</code> generalizes beyond iterators, to other generic types.</li>
<li>Functors encapsulate data <q>unboxing</q>, with applications in
composition and error propagation.</li>
<li>With higher kinded types, we can express constructs like functors
using generics which themselves have type parameters.</li>
</ul>
]]></description>
      <pubDate>Fri, 06 Sep 2019 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/08/10/common-algorithms.html</link>
      <guid>https://vladris.com/blog/2019/08/10/common-algorithms.html</guid>
      <title><![CDATA[Common Algorithms]]></title>
      <description><![CDATA[<h1>Common Algorithms</h1>

<p>This blog post is an excerpt from my book, <a href="https://www.manning.com/books/programming-with-types">Programming with
Types</a>. The code
samples are in TypeScript. If you enjoy the article, you can use the
discount code <strong>vlri40</strong> for a 40% discount on the book.</p>

<h2>A Few Common Algorithms</h2>

<p>There are many algorithms commonly used to process a sequence of data.
Let's list a few of them. We will not look at the implementation, just
describe what arguments besides the iterable they expect and how they
process the data. We'll also mention some synonyms under which the
algorithm might appear.</p>

<ul>
<li><code>map()</code> takes a sequence of <code>T</code> values, a function <code>(value: T) =&gt; U</code>
and returns a sequence of <code>U</code> values applying the function to all
the elements in the sequence. It is also known as <code>fmap()</code>,
<code>select()</code>.</li>
<li><code>filter()</code> takes a sequence of <code>T</code> values, a predicate
<code>(value: T) =&gt; boolean</code> and returns a sequence of <code>T</code> values
containing all the items for which the predicate returns true. It is
also known as <code>where()</code>.</li>
<li><code>reduce()</code> takes a sequence of <code>T</code> values, an initial value of type
<code>T</code>, and an operation which combines two <code>T</code> values into one
<code>(x: T, y: T) =&gt; T</code>. It returns a single value <code>T</code> after combining
all the elements in the sequence using the operation. It is also
known as <code>fold()</code>, <code>collect()</code>, <code>accumulate()</code>, <code>aggregate()</code>.</li>
<li><code>any()</code> takes a sequence of <code>T</code> values and a predicate
<code>(value: T) =&gt; boolean</code>. It returns true if any one of the elements
of the sequence satisfies the predicate.</li>
<li><code>all()</code> takes a sequence of <code>T</code> values and a predicate
<code>(value: T) =&gt; boolean</code>. It returns true if all of the elements of
the sequence satisfy the predicate.</li>
<li><code>none()</code> takes a sequence of <code>T</code> values and a predicate
<code>(value: T) =&gt; boolean</code>. It returns true if none of the elements of
the sequence satisfy the predicate.</li>
<li><code>take()</code> takes a sequence of <code>T</code> values and a number <code>n</code>. It returns
a sequence consisting of the first <code>n</code> elements of the original
sequence. It is also known as <code>limit()</code>.</li>
<li><code>drop()</code> takes a sequence of <code>T</code> values and a number <code>n</code>. It returns
a sequence consisting of all the elements of the original sequence
except the first <code>n</code>. The first <code>n</code> elements are dropped. It is also
known as <code>skip()</code>.</li>
<li><code>zip()</code> takes a sequence of <code>T</code> values and a sequence of <code>U</code> values.
It returns a sequence containing pairs of <code>T</code> and <code>U</code> values,
effectively <q>zipping</q> together the two sequences.</li>
</ul>

<p>There are many more algorithms for sorting, reversing, splitting and
concatenating sequences. The good news is that, because these algorithms
are so useful and generally applicable, we don't need to implement
them. Most languages have libraries which provide these algorithms and
more. For JavaScript, there is the <code>underscore.js</code> package and the
<code>lodash</code> package, both providing a plethora of such algorithms (at the
time of writing, these libraries don't support iterators, only the
JavaScript built-in array and object types). In Java, they are found in
the <code>java.util.stream package</code>. In C# they are in the <code>System.Linq</code>
namespace. In C++ they are found in the <code>&lt;algorithm&gt;</code> standard library
header.</p>

<h2>Algorithms Instead of Loops</h2>

<p>While you might be surprised, a good rule of thumb is to check, whenever
you find yourself writing a loop, whether there is a library algorithm
or a pipeline that can do the job. Usually we write loops to process a
sequence - exactly what the algorithms we talked about do.</p>

<p>The reason to prefer library algorithms to custom code in loops is that
there is less opportunity for mistakes: library algorithms are tried and
tested, implemented efficiently, and the code we end up with is easier
to understand as the operations are spelled out.</p>

<h2>Implementing a Fluent Pipeline</h2>

<p>Most libraries also provide a fluent API to chain algorithms together
into a pipeline. Fluent APIs are APIs based on method chaining, making
the code much easier to read. To see the difference between a fluent and
a non-fluent API, let's take a look at a simple filter/reduce pipeline.</p>

<p>Let's start with a simple implementation of the two algorithms. To
implement <code>filter()</code> we can use a generator. We take an <code>Itreable&lt;T&gt;</code> as
the input sequence and a predicate from <code>T</code> to <code>boolean</code>, and return
another sequence as an <code>IterableIterator&lt;T&gt;</code>. <code>ItreableIterator</code> is the
return type of all generators in TypeScript. The function will simply
traverse the sequence and for each element, if the predicate returns
true, yield the element to the caller:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="o">*</span><span class="nx">filter</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">items</span><span class="o">:</span><span class="w"> </span><span class="kt">Iterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">pred</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kt">boolean</span><span class="p">)</span>
<span class="w">    </span><span class="o">:</span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">item</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">items</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">pred</span><span class="p">(</span><span class="nx">item</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">yield</span><span class="w"> </span><span class="nx">item</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>reduce()</code> takes an <code>Iterable&lt;T&gt;</code> as the input sequence and an initial
value of type <code>T</code>. It also takes a function <code>(T, T) =&gt; T</code> which combines
(reduces) two values of type <code>T</code> into one. This function iterates over
the sequence and reduces all the elements to a single value, which it
returns:</p>
<div class="highlight"><pre><span/><span class="kd">function</span><span class="w"> </span><span class="nx">reduce</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">(</span>
<span class="w">    </span><span class="nx">items</span><span class="o">:</span><span class="w"> </span><span class="kt">Iterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">    </span><span class="nx">init</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span>
<span class="w">    </span><span class="nx">op</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">T</span><span class="p">)</span>
<span class="w">    </span><span class="o">:</span><span class="w"> </span><span class="nx">T</span><span class="w"> </span><span class="p">{</span><span class="w">    </span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">init</span><span class="p">;</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">item</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">items</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">op</span><span class="p">(</span><span class="nx">result</span><span class="p">,</span><span class="w"> </span><span class="nx">item</span><span class="p">);</span><span class="w">    </span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Now let's look at how we could combine these algorithms into a pipeline
which sums up all even values of an array. We will pass the array to
<code>filter()</code> first, with a predicate which returns true for even numbers.
Next, we will reduce the resulting sequence using an initial value of 0
and the function <code>(x, y) =&gt; x + y</code>:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">sequence</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"> </span><span class="mf">6</span><span class="p">];</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span>
<span class="w">    </span><span class="nx">reduce</span><span class="p">(</span>
<span class="w">        </span><span class="nx">filter</span><span class="p">(</span>
<span class="w">            </span><span class="nx">sequence</span><span class="p">,</span>
<span class="w">            </span><span class="p">(</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mf">0</span><span class="p">),</span>
<span class="w">        </span><span class="mf">0</span><span class="p">,</span>
<span class="w">        </span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">y</span><span class="p">);</span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
</pre></div>

<p>Even though we apply <code>filter()</code> first, then pass the result to
<code>reduce()</code>, if we read the code from left to right, we see <code>reduce()</code>
before <code>filter()</code>. It's also a bit hard to make sense of which
arguments go with which function in the pipeline. Fluent APIs make the
code much easier to read. Currently, all our algorithms take an iterable
as the first argument and return an iterable. We can use object-oriented
programming to improve our API. We can put all our algorithms into a
class which wraps an iterable. Then we can call any of them without
explicitly providing an iterable as the first argument - the iterable
is a member of the class. Let's do this for <code>map()</code>, <code>filter()</code>, and
<code>reduce()</code>, by grouping them into a new <code>FluentIterable&lt;T&gt;</code> class
wrapping an iterable:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">iter</span><span class="o">:</span><span class="w"> </span><span class="kt">Iterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">iter</span><span class="o">:</span><span class="w"> </span><span class="kt">Iterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">iter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">iter</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="o">*</span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">item</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">iter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">yield</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="o">*</span><span class="nx">filter</span><span class="p">(</span><span class="nx">pred</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">item</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kt">boolean</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">iter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">pred</span><span class="p">(</span><span class="nx">value</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">yield</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">reduce</span><span class="p">(</span><span class="nx">init</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">op</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">T</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="nx">T</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">init</span><span class="p">;</span>

<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">iter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">op</span><span class="p">(</span><span class="nx">result</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>We can create a <code>FluentIterable&lt;T&gt;</code> out of an <code>Iterable&lt;T&gt;</code>, so we can
rewrite our filter/reduce pipeline into a more fluent form. We create a
<code>FluentIterable&lt;T&gt;</code>, call <code>filter()</code> on it, then we create a new
<code>FluentIterable&lt;T&gt;</code> out of its result, and call <code>reduce()</code> on it:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">sequence</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"> </span><span class="mf">6</span><span class="p">];</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">=</span>
<span class="w">    </span><span class="ow">new</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="p">(</span>
<span class="w">        </span><span class="ow">new</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="p">(</span>
<span class="w">            </span><span class="nx">sequence</span><span class="w">  </span>
<span class="w">        </span><span class="p">).</span><span class="nx">filter</span><span class="p">((</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w">    </span>
<span class="w">    </span><span class="p">).</span><span class="nx">reduce</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">y</span><span class="p">);</span><span class="w">    </span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
</pre></div>

<p>Now <code>filter()</code> appears before <code>reduce()</code>, and it's very clear which
arguments go to which function. The only problem is we need to create a
new <code>FluentIterable&lt;T&gt;</code> after each function call. We can improve our API
by having our <code>map()</code> and <code>filter()</code> functions return a
<code>FluentIterable&lt;T&gt;</code> instead of the default <code>IterableIterator&lt;T&gt;</code>. Note
we don't need to change <code>reduce()</code>, because <code>reduce()</code> returns a single
value of type <code>T</code>, not an iterable.</p>

<p>Since we're using generators, we can't simply change the return type.
Generators exist to provide convenient syntax for functions, but they
always return an <code>IterableIterator&lt;T&gt;</code>. What we can do instead is to
move the implementations to a couple of private methods, <code>mapImpl()</code> and
<code>filterImpl()</code>, and handle the conversion from <code>IterableIterator&lt;T&gt;</code> to
<code>FluentIterable&lt;T&gt;</code> in the public <code>map()</code> and <code>reduce()</code> methods:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">iter</span><span class="o">:</span><span class="w"> </span><span class="kt">Iterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">;</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">iter</span><span class="o">:</span><span class="w"> </span><span class="kt">Iterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">iter</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">iter</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">map</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">item</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">mapImpl</span><span class="p">(</span><span class="nx">func</span><span class="p">));</span><span class="w">    </span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="o">*</span><span class="nx">mapImpl</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">func</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">item</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">U</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">iter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">    </span>
<span class="w">            </span><span class="k">yield</span><span class="w"> </span><span class="nx">func</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">filter</span><span class="o">&lt;</span><span class="nx">U</span><span class="o">&gt;</span><span class="p">(</span><span class="nx">pred</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">item</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kt">boolean</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">filterImpl</span><span class="p">(</span><span class="nx">pred</span><span class="p">));</span><span class="w">    </span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="o">*</span><span class="nx">filterImpl</span><span class="p">(</span><span class="nx">pred</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">item</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="kt">boolean</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="nx">IterableIterator</span><span class="o">&lt;</span><span class="nx">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">iter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w">    </span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">pred</span><span class="p">(</span><span class="nx">value</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">                </span><span class="k">yield</span><span class="w"> </span><span class="nx">value</span><span class="p">;</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">reduce</span><span class="p">(</span><span class="nx">init</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">op</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">T</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="nx">T</span><span class="w"> </span><span class="p">{</span><span class="w">    </span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">T</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">init</span><span class="p">;</span>

<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">const</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">iter</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">op</span><span class="p">(</span><span class="nx">result</span><span class="p">,</span><span class="w"> </span><span class="nx">value</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>With this updated implementation, we can more easily chain the
algorithms, as each returns a <code>FluentIterable</code>, which contains all the
algorithms as methods:</p>
<div class="highlight"><pre><span/><span class="kd">const</span><span class="w"> </span><span class="nx">sequence</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span><span class="mf">1</span><span class="p">,</span><span class="w"> </span><span class="mf">2</span><span class="p">,</span><span class="w"> </span><span class="mf">3</span><span class="p">,</span><span class="w"> </span><span class="mf">4</span><span class="p">,</span><span class="w"> </span><span class="mf">5</span><span class="p">,</span><span class="w"> </span><span class="mf">6</span><span class="p">];</span>

<span class="kd">const</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">number</span><span class="w"> </span><span class="o">=</span>
<span class="w">    </span><span class="ow">new</span><span class="w"> </span><span class="nx">FluentIterable</span><span class="p">(</span><span class="nx">sequence</span><span class="p">)</span>
<span class="w">        </span><span class="p">.</span><span class="nx">filter</span><span class="p">((</span><span class="nx">value</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">value</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mf">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mf">0</span><span class="p">)</span><span class="w">    </span>
<span class="w">        </span><span class="p">.</span><span class="nx">reduce</span><span class="p">(</span><span class="mf">0</span><span class="p">,</span><span class="w"> </span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="w"> </span><span class="nx">y</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="nx">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nx">y</span><span class="p">);</span><span class="w">    </span>

<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
</pre></div>

<p>Now, in true fluent fashion, the code reads easily from left to right
and we can chain any number of algorithms that make up our pipeline with
a very natural syntax. Most algorithm libraries take a similar approach,
making it as easy as possible to chain multiple algorithms together.</p>

<p>Depending on the programming language, one downside of a fluent API
approach is that our <code>FluentIterable</code> ends up containing all the
algorithms, so it is difficult to extend - if it is part of a library,
calling code can't easily add a new algorithm without modifying the
class. C# provides extension methods, which enable us to add methods to
a class or interface without modifying its code. Not all languages have
such features though. That being said, in most situations you should be
using an existing algorithm library, not implementing a new one from
scratch.</p>
]]></description>
      <pubDate>Sat, 10 Aug 2019 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/07/16/a-switchless-state-machine.html</link>
      <guid>https://vladris.com/blog/2019/07/16/a-switchless-state-machine.html</guid>
      <title><![CDATA[A Switchless State Machine]]></title>
      <description><![CDATA[<h1>A Switchless State Machine</h1>

<p>This blog post is an excerpt from my book, <a href="https://www.manning.com/books/programming-with-types">Programming with
Types</a>. The code
samples are in TypeScript.</p>

<h2>Early Programming with Types</h2>

<p>While working on an early draft of the book, I wrote a small script to
help me keep the source code in sync with the text. The draft was
written in the popular Markdown format. I kept the source code in
separate TypeScript files so I could compile them and ensure that, even
if I update the code samples, they still work.</p>

<p>I needed a way to ensure that the Markdown text always contains the
latest code samples. The code samples always appear between a line
containing <code>```ts</code> and a line containing <code>```</code>. When generating
HTML from the Markdown source, <code>```ts</code> is interpreted as the beginning
of a TypeScript code block, which gets rendered using TypeScript syntax
highlighting, while <code>```</code> marks the end of that code block. The contents
of these code blocks had to be inlined from actual TypeScript source files
which I could compile and validate outside of the text.</p>

<p><img src="https://vladris.com/blog/2019/07/16/manuscript.png" alt="image"/></p>

<p>The figure shows two TypeScript (.ts) files containing code samples which
should be inlined in the Markdown document between <code>```ts</code> and
<code>```</code> markers. The <code>&lt;!-- ... --&gt;</code> comments annotate the code samples for
my script.</p>

<p>To determine which code sample goes where, I relied on a small trick: Markdown
allows raw HTML in the document text. I annotated each code sample with an
HTML comment, for example <code>&lt;!-- sample1 --&gt;</code>. HTML comments do not get
rendered, so when converting Markdown to HTML, these became invisible. On the
other hand, my script could use these to determine which code sample to inline
where.</p>

<p>Once all code samples were loaded from disk, I had to process each Markdown
document of the draft and produce an updated version as follows:</p>

<ul>
<li>In text processing mode, simply copy each line of the input text to the
output document as-is. Once a marker is encountered (<code>&lt;!-- sample --&gt;</code>),
grab the corresponding code sample and switch to marker processing mode.</li>
<li>In marker processing mode, again copy each line of the input text to the
output document until we encounter a code block marker (<code>```ts</code>).
Once the code marker is encountered, output the latest version of the code
sample as loaded from the TypeScript file and switch to code processing mode.</li>
<li>In code processing mode, we already ensured the latest version of the code is
in the output document, so we can skip over the potentially outdated version
in the code block. That means we skip each line until we encounter the end of
code block marker (<code>```</code>). Then we switch back to text processing
mode.</li>
</ul>

<p>With each run, the existing code samples in the document preceded by a
<code>&lt;!-- ... --&gt;</code> marker get updated to the latest version of the TypeScript files
on disk. Other code blocks that aren't preceded by <code>&lt;!-- ... --&gt;</code> don't get
updated as they are processed in text processing mode.</p>

<p>As an example, let's take a <code>helloWorld.ts</code>code sample:</p>
<div class="highlight"><pre><span/><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Hello world!"</span><span class="p">);</span>
</pre></div>

<p>We want to embed this in <code>Chapter1.md</code> and make sure it's kept up to date.</p>
<div class="highlight"><pre><span/><span class="gh"># Chapter 1</span>

Printing "Hello world!".
&lt;!-- helloWorld --&gt;
<span class="sb">```ts</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">"Hello"</span><span class="p">);</span>
<span class="sb">```</span>
</pre></div>

<p>This is not quite up to date, the string here is <code>"Hello"</code>, not matching
<code>helloWorld.ts</code>.</p>

<p>This document gets processed line by line as follows:</p>

<ol>
<li>In text processing mode,<code>"# Chapter 1"</code> is copied to the output as-is.</li>
<li><code>""</code> (blank line) is copied to the output as-is.</li>
<li><code>"Printing "Hello world!"."</code> is copied to the output as-is.</li>
<li><code>"&lt;!-- helloWorld --&gt;"</code> is copied to the output as-is. This is a marker
though, so we keep track of the code sample to be inlined (helloWorld.ts)
and switch to marker processing mode.</li>
<li><code>"```ts"</code> is copied to the output as-is. This is a code block marker,
so immediately after copying it to the output we also output the contents
of <code>helloWorld.ts</code>. We also switch to code processing mode.</li>
<li><code>"console.log("Hello");"</code> is skipped. We don't copy lines in code
processing mode, as we are replacing them with the latest in the
code sample file.</li>
<li><code>```</code> is an end of code block marker. We insert it then switch
back to text processing mode.</li>
</ol>

<h2>State Machines</h2>

<p>The behavior of our text processing script is best modelled as a state
machine. A state machine has a set of states and a set of transitions
between pairs of states. The machine starts in a given state, also known
as the <em>start state</em>, then if certain conditions are met, it can
transition to another state.</p>

<p>This is exactly what our text processor does, with its three processing
modes. Input lines are processed a certain way when in <em>text processing
mode</em>. When some condition is met (a <code>&lt;!-- sample --&gt;</code> marker is
encountered), our processor transitions to the marker processing mode.
Again, when some other condition is met (<code>```ts</code> code block marker
encountered), it transitions to <em>code processing mode</em>. When the end of the
code block marker is encountered (<code>```</code>), it transitions back to
<em>text processing mode</em>.</p>

<p><img src="https://vladris.com/blog/2019/07/16/state-machine.png" alt="image"/></p>

<p>The figure shows a text processing state machine with the three states (text
processing, marker processing, code processing) and transitions between the
states based on input. Text processing is the initial state or start state.</p>

<p>Now that we modeled the solution, let's look at how we would implement it. One
way to implement a state machine is by defining the set of states as an
enumeration, keeping track of the current state, and get the desired behavior
with a <code>switch</code> statement that covers all possible states. In our case, we can
define a <code>TextProcessingMode</code> enum.</p>

<p>Our<code>TextProcessor</code> class will keep track of the current state in a <code>mode</code>
property, and implement the switch statement in a <code>processLine()</code> method.
Depending on the state, this method will in turn invoke one of the three
processing methods, <code>processTextLine()</code>, <code>processMarkerLine()</code>, or
<code>processCodeLine()</code>. These functions will implement the text processing then,
when appropriate, transition to another state by updating the current state.</p>

<p>Processing a Markdown document consisting of multiple lines of text means
processing each line in turn using our state machine then returning the final
result to the caller:</p>
<div class="highlight"><pre><span/><span class="kd">enum</span><span class="w"> </span><span class="nx">TextProcessingMode</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">Text</span><span class="p">,</span>
<span class="w">    </span><span class="nx">Marker</span><span class="p">,</span>
<span class="w">    </span><span class="nx">Code</span><span class="p">,</span>
<span class="p">}</span>

<span class="kd">class</span><span class="w"> </span><span class="nx">TextProcessor</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">mode</span><span class="o">:</span><span class="w"> </span><span class="kt">TextProcessingMode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">TextProcessingMode</span><span class="p">.</span><span class="nx">Text</span><span class="p">;</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">codeSample</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="nx">processText</span><span class="p">(</span><span class="nx">lines</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">mode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">TextProcessingMode</span><span class="p">.</span><span class="nx">Text</span><span class="p">;</span>

<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">line</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">lines</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">processLine</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">processLine</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">mode</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">case</span><span class="w"> </span><span class="nx">TextProcessingMode.Text</span><span class="o">:</span>
<span class="w">                </span><span class="kt">this.processTextLine</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
<span class="w">                </span><span class="k">break</span><span class="p">;</span>
<span class="w">            </span><span class="k">case</span><span class="w"> </span><span class="nx">TextProcessingMode.Marker</span><span class="o">:</span>
<span class="w">                </span><span class="kt">this.processMarkerLine</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
<span class="w">                </span><span class="k">break</span><span class="p">;</span>
<span class="w">            </span><span class="k">case</span><span class="w"> </span><span class="nx">TextProcessingMode.Code</span><span class="o">:</span>
<span class="w">                </span><span class="kt">this.processCodeLine</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
<span class="w">                </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">processTextLine</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"&lt;!--"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">loadCodeSample</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">mode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">TextProcessingMode</span><span class="p">.</span><span class="nx">Marker</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">processMarkerLine</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"```ts"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">codeSample</span><span class="p">);</span>

<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">mode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">TextProcessingMode</span><span class="p">.</span><span class="nx">Code</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">processCodeLine</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"```"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">mode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">TextProcessingMode</span><span class="p">.</span><span class="nx">Text</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">loadCodeSample</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="cm">/* Load sample based on marker, store in this.codeSample  */</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>We omitted the code to actually load a sample from an external file as
it isn't particularly relevant to our state machine discussion. This
implementation works but it can be simplified if we use a pluggable
function.</p>

<p>Note that all our text processing functions have the same signature:
they take a line of text as a <code>string</code> argument and return <code>void</code>. What
if, instead of having <code>processLine()</code> implement a big switch statement
and forward to the appropriate function, we make <code>processLine()</code> <em>be</em>
one of those functions?</p>

<p>Instead of implementing <code>processLine()</code> as a method, we can define it as
a property of the class with type <code>(line: string) =&gt; void</code> and
initialize it with <code>processTextLine()</code>. Then, in each of the three text
processing methods, instead of setting <code>mode</code> to a different enum value,
we set <code>processLine()</code> to a different method. In fact, we no longer need
to externally keep track of our state. We don't even need an enum:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">TextProcessor</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">processLine</span><span class="o">:</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="p">=&gt;</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">processTextLine</span><span class="p">;</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">codeSample</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>

<span class="w">    </span><span class="nx">processText</span><span class="p">(</span><span class="nx">lines</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[];</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">processLine</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">processTextLine</span><span class="p">;</span>

<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">line</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">lines</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">processLine</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">processTextLine</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"&lt;!--"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">loadCodeSample</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">processLine</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">processMarkerLine</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">processMarkerLine</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"```ts"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">codeSample</span><span class="p">);</span>

<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">processLine</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">processCodeLine</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">processCodeLine</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="ow">void</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"```"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">processLine</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">processTextLine</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span><span class="w">        </span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">loadCodeSample</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="cm">/* Load sample based on marker, store in this.codeSample  */</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>The second implementation gets rid of the <code>TextProcessingMode</code> enum, the
<code>mode</code> property, and the switch statement which forwarded processing to
the appropriate method. Instead of handling forwarding, <code>processLine()</code>
now <em>is</em> the appropriate processing method.</p>

<p>This implementation removes the need to keep track of states separately
and keep that in sync with the processing logic. If we ever wanted to
introduce a new state, the old implementation would've forced us to
update the code in several places. Besides implementing the new
processing logic and state transitions, we would've had to update the
enum and add another case to the switch statement. Our alternative
implementation removes the need for that: a state is represented purely
by a function.</p>

<h2>State Machines with Sum Types</h2>

<p>One caveat to this is that, for state machines with many states,
capturing states and even transitions explicitly might make the code
easier to understand. Even so, instead of using enums and switch
statements, another possible implementation is to represent each state
as a separate type and the whole state machine as a sum type of the
possible states. This allows us to break it apart into type-safe
components. Below is an example of how we would implement the above
state machine using a sum type. The code is a bit more verbose, so if
possible, we should try the implementation we discussed so far, but this
is another alternative to a switch-based state machine.</p>

<p>Using a sum type, each state is represented by a different type, so we
have a <code>TextLineProcessor</code>, a <code>MarkerLineProcessor</code>, and a
<code>CodeLineProcessor</code>. Each of them keeps track of the processed lines so
far in a result member and provides a <code>process()</code> method to handle a
line of text:</p>
<div class="highlight"><pre><span/><span class="kd">class</span><span class="w"> </span><span class="nx">TextLineProcessor</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[];</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">process</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">TextLineProcessor</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">MarkerLineProcessor</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"&lt;!--"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">MarkerLineProcessor</span><span class="p">(</span>
<span class="w">                </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">,</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">loadCodeSample</span><span class="p">(</span><span class="nx">line</span><span class="p">));</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nx">loadCodeSample</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="cm">/* Load sample based on marker, store in this.codeSample */</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span><span class="w"> </span><span class="nx">MarkerLineProcessor</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[];</span>
<span class="w">    </span><span class="nx">codeSample</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[],</span><span class="w"> </span><span class="nx">codeSample</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">codeSample</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">codeSample</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">process</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">MarkerLineProcessor</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">CodeLineProcessor</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"```ts"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">concat</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">codeSample</span><span class="p">);</span>

<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">CodeLineProcessor</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kd">class</span><span class="w"> </span><span class="nx">CodeLineProcessor</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[];</span>

<span class="w">    </span><span class="kr">constructor</span><span class="p">(</span><span class="nx">result</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[])</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="nx">process</span><span class="p">(</span><span class="nx">line</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="nx">CodeLineProcessor</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">TextLineProcessor</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="nx">line</span><span class="p">.</span><span class="nx">startsWith</span><span class="p">(</span><span class="s2">"```"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>

<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">TextLineProcessor</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">result</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="k">this</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kd">function</span><span class="w"> </span><span class="nx">processText</span><span class="p">(</span><span class="nx">lines</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nx">processor</span><span class="o">:</span><span class="w"> </span><span class="kt">TextLineProcessor</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">MarkerLineProcessor</span>
<span class="w">        </span><span class="o">|</span><span class="w"> </span><span class="nx">CodeLineProcessor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">TextLineProcessor</span><span class="p">([]);</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kd">let</span><span class="w"> </span><span class="nx">line</span><span class="w"> </span><span class="k">of</span><span class="w"> </span><span class="nx">lines</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="nx">processor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">processor</span><span class="p">.</span><span class="nx">process</span><span class="p">(</span><span class="nx">line</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nx">processor</span><span class="p">.</span><span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>All our processors return a processor instance. Either <code>this</code>, if there
is no state change, or a new processor as state changes. The
<code>processText()</code> runs the state machine by calling <code>process()</code> on each
line of text and updating processor as state changes by reassigning it
to the result of the method call.</p>

<p>Now the set of states is explicitly spelled out in the signature of the
processor variable, which can be a <code>TextLineProcessor</code> or a
<code>MarkerLineProcessor</code>, or a <code>CodeLineProcessor</code>.</p>

<p>The possible transitions are captured in the signatures of the
<code>process()</code> methods - for example <code>TextLineProcessor.process()</code> returns
<code>TextLineProcessor | MarkerLineProcessor</code>, meaning it can either stay in
the same state (<code>TextLineProcessor</code>) or transition to the
<code>MarkerLineProcessor</code> state. These state classes can have more
properties and members if needed. This implementation is slightly longer
than the one relying on functions, so if we don't need the extra
features, we are better off using the simpler solution.</p>

<h2>State Machine Implementation Recap</h2>

<p>Let's quickly review the alternative implementations discussed.</p>

<ul>
<li>The <q>classical</q> implementation of a state machine uses an enum to
define all the possible states, a variable of that enum type to keep
track of the current state, and a big switch statement to determine
which processing should be performed based on the current state.
State transitions are implemented by updating the current state
variable. The drawback of this implementation is that states are
completely removed from the processing we want to run during each
state, so the compiler can't prevent mistakes when we run the wrong
processing while in a given state. For example, nothing stops us
from calling <code>processCodeLine()</code> even when we're in
<code>TextProcessingCode.Text</code>. We also have to maintain state and
transitions as a separate enum, with the risk of running out of sync
(for example we might add a new value to the enum but forget to add
a case for it in the switch statement).</li>
<li>The functional implementation represents each processing state as a
function and relies on a function property to track the current
state. State transitions are implemented by assigning the function
property to another state. This is a lightweight implementation
which should work for many cases. The drawbacks are sometimes we
need to associate more information with each state, and sometimes we
might want to be explicit when declaring what the possible states
and transitions are.</li>
<li>The sum type implementation represents each processing state as a
class and relies on a variable representing the sum type of all the
possible states to keep track of the current state. State
transitions are implemented by re-assigning the variable to another
state. This allows us to add additional properties and members to
each state and keep them grouped together. The drawback is that the
code is more verbose than the functional alternative.</li>
</ul>
]]></description>
      <pubDate>Tue, 16 Jul 2019 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2019/04/28/programming-with-types.html</link>
      <guid>https://vladris.com/blog/2019/04/28/programming-with-types.html</guid>
      <title><![CDATA[Programming with Types]]></title>
      <description><![CDATA[<h1>Programming with Types</h1>

<p>I'm happy to announce the early access launch of my book, <a href="https://www.manning.com/books/programming-with-types">Programming
with Types</a>.</p>

<p>This is the culmination of several years of geeking out on type systems
and software correctness. I've always liked to learn how to write
better code, but if I were to point out exactly when I started down this
particular rabbit hole, I'd say it was 2015.</p>

<p>I was switching teams at that point and decided to get up to speed on
modern C++. I started by watching C++ conference videos and was
mind-blown by the <a href="https://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning">C++
Seasoning</a>
talk Sean Parent gave at Going Native a couple of years before. That
gave me a completely different perspective on generic programming.</p>

<p>On a parallel thread, I was playing with Haskell and learning about the
advanced features of its type system. Programming in a functional
language makes it obvious how some of the features taken from granted in
such languages get adopted by more mainstream languages as time goes by.
Closures, sum types, and monads are slowly making their way to the
mainstream.</p>

<h2>Bibliography</h2>

<p>In awe of the elegance of generics and trying to learn more about them,
I picked up Stepanov's <a href="https://www.goodreads.com/book/show/23498372-from-mathematics-to-generic-programming">From Mathematics to Generic
Programming</a>
and <a href="https://www.goodreads.com/book/show/6142482-elements-of-programming">Elements of
Programming</a>.
I realized I need a refresher on abstract algebra, so I took a detour
and went through Pinter's <a href="https://www.goodreads.com/book/show/8295305-a-book-of-abstract-algebra">A Book of Abstract
Algebra</a>.</p>

<p>Getting a sense of the mathematical underpinnings of generics made
things much clearer for me. I wanted to get a similar understanding of
the math underlying the Haskell type system, namely category theory. A
great resource on category theory is Bartosz Milewski's <a href="https://www.goodreads.com/book/show/33618151-category-theory-for-programmers">Category
Theory for
Programmers</a>.</p>

<p>Deeper still down the rabbit hole, I picked up Benjamin Pierce's famous
<a href="https://www.goodreads.com/book/show/112252.Types_and_Programming_Languages">Types and Programming
Languages</a>.
The book covers many aspects of type systems, from basic types and
function types, to subtyping, generics, and higher-kinded types. In
fact, this is exactly the progression my own book follows. Types and
Programming Languages is geared towards compiler writers. I wanted to
write something that can benefit any developer.</p>

<h2>From Theory to Practice</h2>

<p>While learning more and more about type systems, I could tell the code I
was writing at work became better. There is a direct link between the
more theoretical realm of type system design and the day-to-day
production software. This isn't a revolutionary discovery - all fancy
type system features exist to solve some real-world problems.</p>

<p>I had new insights which I could use and did my best to share them. I
started this blog and posted about various practical applications. I did
hundreds of code reviews and applied what I learned there. And here is
where I found my niche.</p>

<p>Not every practicing programmer has the time and patience to read
highly-theoretical books, with mathematical proofs. On the other hand, I
could tell that my time wasn't wasted reading such books - they made me
a better software engineer. I figured there is room for a book which
covers type systems and the safety features they provide, with practical
applications anyone can use in their day jobs.</p>

<h2>Programming with Types {#programming-with-types-1}</h2>

<p>The book starts with basic types and some of their common pitfalls:
numerical types tend to overflow or are subject to rounding errors,
strings have several encodings, and manipulating them naively causes all
sorts of issues. There are lesser known basic types, like the empty type
and the unit type, which are not as popular for some reason, even though
they have great applications: as return types for functions which never
return, or don't return anything meaningful.</p>

<p>After basic types, the book covers composition. Why record types are
generally better than tuples, what algebraic data types are about, and
countless applications of sum types. Functions should return either a
valid value or an error, never both. The variant design pattern,
enabling double-dispatch, looks different today than it did a few years
ago.</p>

<p>Function types are discussed at length, from lambdas and the functional
staples <code>map</code>, <code>filter</code>, and <code>reduce</code>, to modern features of programming
languages like <code>yield</code> and <code>async</code>/<code>await</code>. The book shows modern takes
on the strategy and decorator design patterns, implemented more
succinctly using function types.</p>

<p>Subtyping is another major topic, covering not only the elements of
object oriented programming and how to use them effectively, but also
variance, top types, and bottom types. For example, we can use a bottom
type to produce a value out of nowhere. Mixins are controversial, as
they are usually implemented as multiple inheritance, but I believe they
are extremely useful when designed correctly.</p>

<p>The next major topic is generic programming. Generic data structures are
responsible for shaping the data, while algorithms are responsible for
processing data. Iterators are a bridge between data structures and
algorithms, allowing us to mix-and-match them. As an example, we can
find an item in a tree using the same code we use to find an item in a
list.</p>

<p>Finally, the book covers higher-kinded types. These are higher-level
abstractions, generic types with generic arguments, which underpin
concepts like functors and monads. The joke goes that as soon as you
understand monads, you lose the ability to explain them. I'm taking it
as a challenge.</p>

<p>Check out my book
<a href="https://www.manning.com/books/programming-with-types">here</a>.</p>
]]></description>
      <pubDate>Sun, 28 Apr 2019 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/12/31/fold.html</link>
      <guid>https://vladris.com/blog/2018/12/31/fold.html</guid>
      <title><![CDATA[Fold]]></title>
      <description><![CDATA[<h1>Fold</h1>

<p>Most object-oriented programming languages represent object instances in
memory in two separate chunks. One of them contains the
instance-specific state - the class attributes. The other one contains
the methods, which are actually shared across instances. Let's take as
an example a simple type with a couple of properties and a method:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Point</span><span class="w"> </span><span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">double</span><span class="w"> </span><span class="n">X</span><span class="p">;</span>
<span class="w">    </span><span class="kt">double</span><span class="w"> </span><span class="n">Y</span><span class="p">;</span><span class="w"> </span>

<span class="w">    </span><span class="kt">double</span><span class="w"> </span><span class="nf">distanceToOrigin</span><span class="p">()</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>If we take two distinct instances of <code>Point</code>, like <code>new Point(10, 5)</code>
and <code>new Point(20, 20)</code>, they have different <code>X</code> and <code>Y</code> coordinates, so
those need to be stored individually. On the other hand, the logic of
<code>distanceToOrigin</code> is the same for both objects. The method evaluates to
different results, because <code>this-&gt;X</code> and <code>this-&gt;Y</code> are different for the
two objects, but the code is the same.</p>

<p>Instead of storing separate copies of the code for each instance, the
method implementations are shared across objects. <code>distanceToOrigin</code> can
return different results for different objects because each invocation
gets a different <code>this</code> pointer to the state of each object. In fact,
under the hood, every class method gets an implicit <code>this</code> argument
which represents the object on which the method is invoked. Python makes
that explicit, requiring all class methods to implement a <code>self</code>
argument in order to reference instance-specific state.</p>

<p>There isn't much difference between a method like
<code>Point::distanceToOrigin</code> and a free function which takes a <code>Point</code> as
an argument:</p>
<div class="highlight"><pre><span/><span class="kt">double</span><span class="w"> </span><span class="nf">distanceToOrigin</span><span class="p">(</span><span class="n">Point</span><span class="w"> </span><span class="n">p</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="cm">/* ... */</span>
<span class="p">}</span>
</pre></div>

<p>The only difference is that a class member gets access to privates,
while an outside function doesn't. Visibility aside, methods of a class
are an independent <q>chunk</q> shared across object instances and the
state of each object is another, separate <q>chunk</q>.</p>

<p>An interpretation of this is that, even though classes contain methods,
object instances of a given type can still be thought of as pure state.
Our <code>new Point(10, 5)</code> is represented by a combination of the <code>Point</code>
class, which includes the method implementations and their memory layout
etc. and instance-specific state. The <code>Point</code> class includes the method
<code>distanceToOrigin</code> with an implicit <code>this</code> argument (and some additional
metadata).</p>

<p>With this view, a <code>Point</code> instance is a pair of values <code>X</code> and <code>Y</code>. Any
particular instance of <code>Point</code> is a member of the set
<code>{ (X, Y) : X â double, Y â double }</code>. The function <code>distanceToOrigin</code>
can be viewed as a function from this set (from the implicit <code>this</code>
argument) to a <code>double</code> value.</p>

<p><code>disntaceToOrigin : { (X, Y) : X â double, Y â double } â double.</code></p>

<h2>Operations and Closures</h2>

<p>A function that takes two arguments of type <code>Point</code> is called a binary
operation on the set. We can represent it as a function
<code>f(Point, Point)</code> or, equivalently, as an operation <code>Point â Point</code>. If
the codomain of the function is also a <code>Point</code>, for example let's take a
function like <code>Point midPoint(Point x, Point y)</code>, which computes the
middle point between two given points, we call the operation <em>closed</em>
over the set.</p>

<p>The notion of closure in algebra is different from the notion closure in
computer science, which deals with context captured in lambdas. In this
case it simply means an operation that combines a number of elements of
a set into another element of the set.</p>

<p>Since we can view any type as a set, and any function taking two
arguments of a type and returning another instance of that type as a
closed binary operation on the set, we can start talking about algebraic
structures.</p>

<h2>Magmas</h2>

<p>A magma is just a set with a closed operation, without any other
constraints imposed. If we have a magma, we can implement an algorithm
like <code>fold</code> which, given a set of values in the magma, combines them
into a single value.</p>

<p>For example we can fold three <code>Point</code> instances <code>a</code>, <code>b</code>, and <code>c</code> into a
single <code>Point</code> using the <code>midPoint</code> function like this:</p>
<div class="highlight"><pre><span/><span class="n">Point</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">midPoint</span><span class="p">(</span><span class="n">midPoint</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">b</span><span class="p">),</span><span class="w"> </span><span class="n">c</span><span class="p">);</span>
</pre></div>

<p>We can sketch out a function that, given a set of objects of any type
<code>T</code> and an operation closed over <code>T</code>, produces a final value of type
<code>T</code>:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Op</span><span class="p">,</span>
<span class="w">    </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">=</span><span class="k">typename</span><span class="w"> </span><span class="nc">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value_type</span><span class="o">&gt;</span>
<span class="n">T</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">begin</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">end</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">init</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">init</span><span class="p">;</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">begin</span><span class="p">;</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">end</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">it</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="n">result</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">it</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This function takes a pair of iterators which we use to traverse the set
of values of type <code>T</code>, an initial value of type <code>T</code>, and a binary
operation <code>Op</code>. We need an initial value of type <code>T</code> because if the set
is empty, we still need to return something from the function. That is,
if the <code>for</code> loop never executes, and we never apply <code>op</code>, we still need
a <code>T</code> to return. In this case we will simply return <code>init</code>.</p>

<p>Since a magma doesn't impose any constraints on the operation, the
order in which we combine elements might be important. For example, for
integers and the subtraction operation, if we start with the set of
number <code>1</code>, <code>2</code>, and <code>3</code>, and an initial value of <code>1</code>, we can fold from
left to right and get <code>((1 - 1) - 2) - 3</code>, or <code>-5</code>. On the other hand,
we can start from right to left, and fold <code>1 - (2 - (3 - 1))</code>, or <code>1</code>.
Let's call this verison <code>foldRight</code> and look at a possible
implementation:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Op</span>
<span class="w">    </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">=</span><span class="k">typename</span><span class="w"> </span><span class="nc">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value_type</span><span class="o">&gt;</span>
<span class="n">T</span><span class="w"> </span><span class="n">fold_right</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">begin</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">end</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">init</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">init</span><span class="p">;</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">end</span><span class="p">;</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">begin</span><span class="p">;</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="o">*</span><span class="p">(</span><span class="o">--</span><span class="n">it</span><span class="p">),</span><span class="w"> </span><span class="n">result</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Note that for an operation like addition, this is not the case: if we
fold <code>1</code>, <code>2</code>, and <code>3</code>, with an initial value of <code>1</code>, we get <code>7</code>
regardless of the direction and whether we make the initial value a left
or a right operand. Let's zoom in on this.</p>

<h2>Semigroups</h2>

<p>If we have a set with a closed operation that is also associative, we
have a <em>semigroup</em>. For an <em>associative</em> operation, it doesn't really
matter what order we apply multiple operations on. For example, for the
set of strings and the string concatenation operation, it doesn't
metter whether we append <code>foo</code> to <code>bar</code>, then the result to <code>baz</code> or
whether we concatenate <code>bar</code> with <code>baz</code> first, then prepend <code>foo</code> to it:</p>
<div class="highlight"><pre><span/><span class="p">(</span><span class="s">"foo"</span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">"bar"</span><span class="n">s</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">"baz"</span><span class="n">s</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="s">"foo"</span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="s">"bar"</span><span class="n">s</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">"baz"</span><span class="n">s</span><span class="p">)</span>
</pre></div>

<p>More formally, an opeartion is associative if, for any <code>a</code>, <code>b</code>, and
<code>c</code>, <code>(a â b) â c == a â (b â c)</code>. That being said, that's not enough
to make our right fold redundant:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="w"> </span><span class="n">elems</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s">"foo"</span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="s">"bar"</span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="s">"baz"</span><span class="n">s</span><span class="w"> </span><span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">elems</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">elems</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span><span class="w"> </span><span class="s">"!"</span><span class="n">s</span><span class="p">,</span>
<span class="w">    </span><span class="p">[](</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">;</span><span class="w"> </span>
<span class="w">    </span><span class="p">});</span>
<span class="c1">// Prints !foobarbaz</span>

<span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">fold_right</span><span class="p">(</span><span class="n">elems</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">elems</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span><span class="w"> </span><span class="s">"!"</span><span class="n">s</span><span class="p">,</span>
<span class="w">    </span><span class="p">[](</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
<span class="w">    </span><span class="p">});</span>
<span class="c1">// Prints foobarbaz!</span>
</pre></div>

<p>It still matters whether our initial value is a left or right argument
to our operation. If for an operation we get the same result regardless
of how we arrange the operands, then we have a <em>commutative</em> operation.
Integer addition is an example of a commutative operation, where <code>1 + 2</code>
is the same as <code>2 + 1</code>. Note this is different than string
concatenation, where <code>"foo"s + "bar"s != "bar"s + "foo"s</code>. A semigroup
with a commutative operation is called an <em>abelian semigroup</em>. Here we
finally no longer need to distinguish between <code>fold</code> and <code>fold_right</code> as
they both produce the same result.</p>

<p>Let's also look at that mandatory initial value.</p>

<h2>Monoids</h2>

<p>The reason we require an initial value is that we need to return
something in case our set is empty, and we don't always have a good
default. That's not always the case. There are operations for which we
have such a default, called the <em>identity</em> of the opeartion. This value,
combined with any other value using the operation, leaves the other
value unchanged. For string concatenation, the identity is the empty
string. For addition, the identity is <code>0</code>. In general, we have
<code>a â id == id â a == a</code> for any <code>a</code>. This is what makes <code>id</code> an
identity.</p>

<p>A semigroup with an identity is a <em>monoid</em>. That's a set with an
associative operation and an identity element. Note commutativity is not
required. If the operation is also commutative, then we have a
<em>commutative monoid</em>.</p>

<p>If the default constructor of our type <code>T</code> creates an identiy, then we
can reimplement <code>fold</code> like this:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Op</span><span class="p">,</span><span class="w"> </span>
<span class="w">    </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">=</span><span class="k">typename</span><span class="w"> </span><span class="nc">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value_type</span><span class="o">&gt;</span>
<span class="n">T</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">begin</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">end</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span><span class="n">result</span><span class="p">{</span><span class="w"> </span><span class="p">};</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">begin</span><span class="p">;</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">end</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">it</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="n">result</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">it</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>We no longer require an initial value to be passed in. That's because,
if we really want to combine all elements with a certain value, we can
do it after calling <code>fold</code>. For example we can concatenate our strings
and then append or prepend our <q>!</q>s:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="w"> </span><span class="n">elems</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="s">"foo"</span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="s">"bar"</span><span class="n">s</span><span class="p">,</span><span class="w"> </span><span class="s">"baz"</span><span class="n">s</span><span class="w"> </span><span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="w"> </span><span class="n">folded</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">elems</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">elems</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span>
<span class="w">    </span><span class="p">[](</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
<span class="c1">// folded is "foobarbaz"s</span>
</pre></div>

<p>Unlike the first implementation, this works for empty sets too:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="w"> </span><span class="n">elems</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="w"> </span><span class="n">folded</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">elems</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">elems</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span>
<span class="w">    </span><span class="p">[](</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
<span class="c1">// folded is the empty string</span>
</pre></div>

<p>This version only works if we have an identity and if the default
constructor actually creates that identity. Note identity is a property
related to the operation, so we need to be careful. The default integer
value is <code>0</code>, which is the identity for addition, so we can very well
sum numbers using the second version of <code>fold</code>. On the other hand, we
can't use it for product:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">elems</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">};</span>

<span class="kt">int</span><span class="w"> </span><span class="n">sum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">elems</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">elems</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span>
<span class="w">    </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">y</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
<span class="c1">// sum is 6</span>

<span class="kt">int</span><span class="w"> </span><span class="n">product</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">elems</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">elems</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span>
<span class="w">    </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">y</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
<span class="c1">// product is 0</span>
</pre></div>

<p>If we default to <code>0</code> and multiply all numbers with it, our product
becomes <code>0</code>. On the other hand, if we do have a default identity, then
<code>fold</code> and <code>fold_right</code> give us the same result even if the operation is
only associative, without necessarily being commutative. That's
because, if our initial value is an identity, it doesn't matter whether
it is a left or right argument to our operation. By definition,
<code>a â id == id â a == a</code> so for a set of values like <code>a</code>, <code>b</code>, and <code>c</code>,
we get:</p>
<div class="highlight"><pre><span/>((id â a) â b) â c == (a â b) â c
</pre></div>

<p>From associativity, we get:</p>
<div class="highlight"><pre><span/>(a â b) â c == a â (b â c)
</pre></div>

<p>We can add another identity in there, since <code>c == c â id</code>:</p>
<div class="highlight"><pre><span/>a â (b â c) == (a â (b â (c â id)))
</pre></div>

<p>We started with how <code>fold</code> evaluates and ended up with how <code>fold_right</code>
evaluates. That means we don't distinguish between a left to right or
right to left fold is either:</p>

<ul>
<li>The operation is associative and commutative (abelian semigroup).</li>
<li>The operation is associative and the initial value is the identity
(monoid with identity as initial value).</li>
</ul>

<p>If neither of these holds, it matters which way the fold happens as we
get different results.</p>

<h2>Parallelized Fold</h2>

<p>Wihout going into too many details, we can also divide &amp; conquer a fold
operation, fold subsets in parallel, then merge the results.
Associativity allows us to do so, as we can split the set of values <code>a</code>,
<code>b</code>, <code>c</code>, and <code>d</code> into <code>left_half = a â b</code> and <code>right_half = c â d</code>,
then combine the two halves for the final result
<code>left_half â right_half</code>. This is the same thing as <code>(a â b) â (c â d)</code>.
As long as the operation is associative, this is the same as
<code>((a â b) â c) â d</code> or <code>a â (b â (c â d))</code>.</p>

<p>Not all operations are associative though, as we saw before. Subtraction
isn't for example. <code>(1 - 2) - (3 - 4)</code> is <code>0</code>. <code>((1 - 2) - 3) - 4</code> is
<code>-8</code>. We can only parallelize folding a semigroup, not any magma.</p>

<p>Here, since we are talking about dividing the input set, we can assume
we have more than zero elements in a subset (otherwise we wouldn't
divide it), so whether we have an identity or not or whether we apply it
to the left or the right can be left to the top function which combines
the partial results.</p>

<h2>Alternatives</h2>

<p>We covered traditional implementations of <code>fold</code> but let's go over a
couple of alternative implementations. We could say that if the set is
empty, we don't return anything, otherwise we take the first element as
our initial value:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Op</span><span class="p">,</span>
<span class="w">    </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">=</span><span class="k">typename</span><span class="w"> </span><span class="nc">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value_type</span><span class="o">&gt;</span>
<span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">begin</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">end</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">begin</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">end</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">nullopt</span><span class="p">;</span>

<span class="w">    </span><span class="n">It</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">begin</span><span class="p">;</span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="p">(</span><span class="n">it</span><span class="o">++</span><span class="p">);</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">end</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">it</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="n">result</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">it</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>As long as the operation is associative, the fold direction doesn't
matter. In case we don't have any value at all, we return <code>nullopt</code> to
signal the absence of a value.</p>

<p>Another option is to take a default value as an argument and return that
in case we have no elements to combine, but if we do, simply ignore that
value instead of combining it with the input elements:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Op</span><span class="p">,</span>
<span class="w">    </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">=</span><span class="k">typename</span><span class="w"> </span><span class="nc">std</span><span class="o">::</span><span class="n">iterator_traits</span><span class="o">&lt;</span><span class="n">It</span><span class="o">&gt;::</span><span class="n">value_type</span><span class="o">&gt;</span>
<span class="n">T</span><span class="w"> </span><span class="n">fold</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">begin</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">end</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">def</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">begin</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">end</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">def</span><span class="p">;</span>

<span class="w">    </span><span class="n">It</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">begin</span><span class="p">;</span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="p">(</span><span class="n">it</span><span class="o">++</span><span class="p">);</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">end</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">it</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="n">result</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">it</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This is similar to the previous implementation, but instead of an empty
optional we return a supplied value in case we don't have anything to
fold. This would be interpreted as <em>fold or return def</em>, as opposed to
our original implementation, which was <em>fold with init</em>.</p>

<h2>Summary</h2>

<p>This post started with a discussion of how types can be viewed as sets
and functions as functions over those sets. We then covered a few
abstract algebra concepts as applied to the <code>fold</code> higher order
function, looking in which situations do <code>fold</code> and <code>fold_right</code> return
the same result.</p>

<ul>
<li>A function <code>T f(T, T)</code> is a closed binary operation on the set <code>T</code>.</li>
<li>A set with a binary operation is called a magma. We can implement a
<code>fold</code> and a <code>fold_right</code> if we have a magma. Both functions need an
initial value.</li>
<li>If the operation is also associative, we have a semigroup. Here it
still matters whether the initial value is applied on the left or
the right, as the results might be different.</li>
<li>If the operation is also commutative, we have an abelian semigroup.
There is no distinction between a left-to-right and a right-to-left
fold for an abelian semigroup.</li>
<li>If the operation has an identity, then we have a monoid. If we use
the identity as an initial value, then we again have no distinctino
between a left-to-right and a right-to-left fold.</li>
<li>We can paralllize fold to take subsets of the input set, combine
them in parallel, then combine the results. Associativity is the
only requirement for this, so we can parallelize folding a
semigroup.</li>
<li>We also looked at a couple of alternative implementations which only
require a semigroup for the fold direction not to matter. The first
one returns an empty optional if there are no values to combine; the
second returns a value supplied as argument, without otherwise
combining it.</li>
</ul>
]]></description>
      <pubDate>Mon, 31 Dec 2018 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/11/18/notes-on-encoding-text.html</link>
      <guid>https://vladris.com/blog/2018/11/18/notes-on-encoding-text.html</guid>
      <title><![CDATA[Notes on Encoding Text]]></title>
      <description><![CDATA[<h1>Notes on Encoding Text</h1>

<p>In this post we will look at text encoding, from the half-a-century old
ASCII and its extensions to Unicode and the common UTF-16 and UTF-8
encodings. We'll cover a few basic text encoding concepts like code
points, graphemes, and surrogate pairs and see how we can stack emojis
and combine them into intricate glyphs.</p>

<h2>ASCII</h2>

<p>The American Standard Code for Information Exchange, or ASCII, was
developed in the 60s. The standard encodes each character in 7 bits, so
it has 128 characters. These include both the lowercase and uppercase
letters of the English alphabet, digits, punctuation, and a set of
control characters like LF (line feed, also known as <code>\n</code>), CR (carriage
return, also known as <code>\r</code>) or BEL (audible beep, or <code>\a</code>). The ASCII
character set contains all characters on a typewriter.</p>
<div class="highlight"><pre><span/>0x00 to 0x1F - control characters
0x20 to 0x2F - symbols - SPACE ! " # $ % &amp; ' ( ) * + , - . /
0x30 to 0x39 - digits - 0 1 2 3 4 5 6 7 8 9
0x3A to 0x40 - symbols - : ; &lt; = &gt; ? @
0x41 to 0x5A - uppercase letters - A to Z
0x5B to 0x60 - symbols â [ \ ] ^ _ `
0x61 to 0x7A - lowercase letters - a to z
0x7B to 0x7E - symbols - { | } ~
0x7F - "delete" control character - DEL
</pre></div>

<h3>Parity bits</h3>

<p>A byte is 8 bits wide, so the remaining bit was used as a <em>parity bit</em>.
The parity bit is 0 if the 7 bits encoding a character have an even
number of 1s and 1 if the bits encoding a character have an odd number
of 1s. For example, the letter <code>A</code> is encoded as <code>0x41</code>, or <code>1000001</code>.
<code>1000001</code> has an even number of bits so the parity bit is 0, thus <code>A</code>
ends up being encoded on 8 bits as <code>01000001</code>. The letter <code>C</code> is encoded
as <code>0x43</code>, or <code>1000011</code>, so the parity bit is 1. <code>C</code> ends up being
encoded on 8 bits as <code>11000011</code>.</p>

<p>The parity bit is used to check the consistency of the data: in a lossy
environment, a parity bit is a simple way to add extra validation. If
the parity bit does not have the expected value - for example it is 1
while the remaining 7 bits have an even number of bits set to 1 - it
means that the data is corrupted.</p>

<p>This encoding was enough for English, but lacked other letters common in
European languages, for example accented letters like Ã© or Ä. It also
could not encode any other alphabets, like Arabic, Cyrillic, Hebrew and
so on.</p>

<h2>Extended ASCII and Code Pages</h2>

<p>The ASCII character set had numerous extensions which started to
leverage the 8th bit to encode information instead of using it to check
integrity. The original 128 character stayed in the <code>0x0</code> - <code>0x7F</code>
range, but with the extra bit, an extended ASCII character set could
encode 128 more characters from <code>0x80</code> to <code>0xFF</code>. Since ASCII received
multiple such extensions, these were distinguished by code pages. A code
page defined what the <code>0x80</code> to <code>0xFF</code> characters are.</p>

<p>IBM PC systems came with the popular <strong>code page 437</strong> which includes
characters for box-drawing like <code>â</code>, <code>â</code>, and <code>â</code>. Text-based user
interface could simulate windows, buttons and so on using these
characters:</p>
<div class="highlight"><pre><span/>ââââââââââââââââââââââââââââââââââââââ
â Box-drawn window with progress bar â
ââââââââââââââââââââââââââââââââââââââ¢
â  ââââââââââââââââââââââââââââââââ  â
ââââââââââââââââââââââââââââââââââââââ
</pre></div>

<p>Another set of extensions was the <strong>ISO/IEC 8859</strong> standard consisting
of 16 parts, each adding support for additional character and alphabets.
For example, part 1 was named <em>Latin-1 Western European</em> and added most
characters required by Western European languages (like accented
letters), while part 5, <em>Latin/Cyrillic</em> used the available 128
characters to encode the Cyrillic alphabet.</p>

<p>While these code pages allowed new ranges of characters, each could only
add 128 symbols, which didn't scale well to the world's written
languages. For perspective, Kanji has thousands of characters.</p>

<h2>Unicode</h2>

<p>The Unicode standard aims to cover most of the world's writing systems
and include additional symbols like emojis.</p>

<h3>Code points</h3>

<p>Unicode introduces the notion of code points. Most code points are
characters, but some code points are used for formatting while some are
unassigned as of today and will be defined in future extensions of the
standard. The total code space of Unicode spans 1114112 code points,
from <code>0x0</code> to <code>0x10FFFF</code>.</p>

<p>The code space is divided into 17 planes, each consisting of a range of
65536 code points (from <code>0x0</code> to <code>0xFFFF</code>, from <code>0x10000</code> to <code>0x1FFFF</code>
and so on until <code>0xF0000</code> to <code>0x10FFFF</code>). A Unicode code point is
conventionally referred to as <code>U+XXX</code> where <code>XXX</code> is the hexadecimal
value of the code point. For example the code point corresponding to the
letter <q>a</q> which is <code>0x61</code>, is referred to as <code>U+0061</code>.</p>

<p>Most programming languages allow strings to contain a Unicode escape
sequence, which gets interpreted as a Unicode code point. Such sequences
start with <code>\x</code> or <code>\u</code> followed by the hexadecimal value of the code
point, for example in JavaScript the Unicode escape for <q>a</q> is the
string <code>"\u0061"</code>.</p>

<p>Not only does Unicode support a huge range of code points, it also
defines combining characters which, combined with other character,
create new characters. For example, Ì (<code>U+0301</code>) is the combining acute
accent. Combining this with <q>a</q> (<code>U+0061</code>) by appending it after the
letter (the string <code>"\u0061\u0301"</code>) results in the character <q>aÌ</q>
while combining it with <q>e</q> (<code>U+0065</code>) in the string <code>"\u0065\u0301"</code>
results in the character <q>eÌ</q>.</p>

<p>Similarly, a skin tone modifier like dark skin tone, ð¿ (<code>U+1F3FF</code>) can
be appended to an emoji like the baby emoji ð¶ (<code>U+1F476</code>) to get a baby
with a dark skin tone ð¶ð¿.</p>

<h3>Graphemes</h3>

<p>A grapheme is a graphical symbol that a user sees on the screen. Text
rendering is done through graphemes. Some graphemes correspond to a
single code point, like <q>a</q> corresponding to <code>U+0061</code>. Other graphemes
correspond to a sequence of code points, like ð¶ð¿, which corresponds to
<code>U+1F476</code> then <code>U+1F3FF</code>. There are also graphemes which can be obtained
in multiple ways. The accented <q>e</q> in the example above, <q>eÌ</q>, can be
obtained by combining the letter <q>e</q> with the acute accent (<code>U+0065</code>
then <code>U+0301</code>), but there is also an accented <q>e</q> character <q>Ã©</q>
represented by the code point <code>U+00E9</code>. Both <code>U+0065 U+0301</code> and
<code>U+00E9</code> resolve to the same grapheme.</p>

<p>Because of such equivalences, the standard defines a normalization
procedure which can convert equivalent texts to the same code point
representation. There are several ways to achieve this, which we'll not
cover in this blog post.</p>

<p>Combining and modifying characters can be stacked one after the other.
For example, the ð¨ââ¤ï¸âð¨ emoji showing two man with a heart above is a single
grapheme but consists of the following sequence of code points:
<code>U+1F468 U+200D U+2764 U+FE0F U+200D U+1F468</code>. This is a combination of:</p>

<ul>
<li>The man emoji ð¨ (<code>U+1F468</code>)</li>
<li>The zero-width joiner (<code>U+200D</code>) which does not have a stand-alone
representation but combines two emojis into a single one</li>
<li>The heavy black heart symbol â¤ (<code>U+2764</code>) - depending on which OS
you are reading this, it might or might not render as an emoji</li>
<li>The Variation Selector-16 character (<code>U+2764</code>) which also doesn't
have a stand-alone representation but can be applied to code points
which have both a text and an emoji representation to select the
emoji representation. This ensures the heavy black heart symbol gets
the emoji representation â¤ï¸.</li>
<li>Another zero-width joiner (<code>U+200D</code>)</li>
<li>Another man emoji ð¨ (<code>U+1F468</code>)</li>
</ul>

<p>The whole sequence results in a single grapheme.</p>

<p>One interesting thing to note is that splitting a string without being
aware of how the code points combine can change the representation of
the text. This can happen when breaking a line of text to fit on screen.
In the above example, even though we have 6 code points, we end up with
a single grapheme, so when dealing with rendering, it's usually best to
operate on graphemes not code points/characters.</p>

<h2>Encodings</h2>

<p>We talked about code points and graphemes, but how are the code points
actually encoded as bytes? With ASCII and the simple extensions, the
encoding was easy, as each byte encoded a character. Unicode has over a
million code points, so let's look at how these get translated into
bytes.</p>

<h3>UTF-32</h3>

<p>The most obvious way is to find the minimum number of bytes that can
encode any code point. Since code points range from <code>0x0</code> to <code>0x10FFFF</code>,
we need 21 bits to store all possible values (<code>0x10FFFF</code> in binary is
<code>0b100001111111111111111</code>).</p>

<p>Because most CPUs nowadays have a word size of at least 32-bits, the
UTF-32 encoding rounds up the number of required bits from 21 to 32,
thus representing a code point using 4 bytes.</p>

<p>This encoding is very straight-forward, as any 4 bytes store the value
of a code point in a string, but it is also very space-inefficient. The
leading bits are always 0 and not only that, the code points
representing common characters and alphabets appear in the lower planes,
so while an emoji like the woman emoji ð© (<code>U+1F469</code>) in binary is
<code>0b11111010001101001</code>, thus requiring at least 17 bits to represent, the
code point for the letter <q>a</q> is <code>U+0061</code>, same as the old ASCII
representation. That is <code>0b1100001</code> in binary, requiring only 7 bits.</p>

<p>To take advantage of this, several <em>variable-length</em> encodings were
developed, which use fewer bytes for code points representable with a
smaller number of bits, and more bytes for higher code point values. The
two most common encodings are UTF-16 and UTF-8.</p>

<h3>UTF-16</h3>

<p>UTF-16 encodes code points in either one or two 16-bit wide code units.
The code points in the range <code>U+0000</code> to <code>U+FFFF</code> are encoded directly
as a 16-bit code unit, except the subrange <code>U+D800</code> to <code>U+DFFF</code> which
we'll talk about shortly. This range corresponds to Plane 0, the <em>Basic
Multilingual Plane</em>, with code points to represent almost all modern
languages.</p>

<p>Code points from other planes are encoded in UTF-16 using two code
units, so 32 bits. Any code point in the range <code>U+10000</code> to <code>U+10FFFF</code>
(or <code>0x10000</code> to <code>0x10FFFF</code>) is encoded by subtracting <code>0x10000</code> leaving
a value between <code>0x0</code> and <code>0xFFFFF</code>. Values in this range can be
represented in 20 bits. A sequence of 10 bits can represent values in
the range <code>0x0</code> to <code>0x3FF</code>. The 20 bits are split into the first (most
significant) 10 bits and the last (least significant) 10 bits. The first
10 bits are added to <code>0xD800</code>, resulting in a value in the range
<code>0xD800</code> to <code>0xDBFF</code>. This is represented in the first 16-bit code
point. The last 10 bits are added to <code>0xDC00</code>, resulting in a value in
the range <code>0xDC00</code> to <code>0xDFFF</code>. This is represented in the second 16-bit
code point.</p>

<p>Let's take as an example the woman emoji ð© (<code>U+1F469</code>). The UTF-16
encoding goes as follows:</p>

<ul>
<li>Subtract <code>0x10000</code> from <code>0x1F469</code>, resulting in <code>0xF469</code>, or
<code>0b00001111010001101001</code> in 20 bits.</li>
<li>The first 10 bits, <code>0b0000111101</code>, or <code>0x3D</code>, are added to <code>0xD800</code>
which gives us <code>0xD83D</code>.</li>
<li>The remaining 10 bits, <code>0b0001101001</code>, or <code>0x69</code>, are added to
<code>0xDC00</code>, giving <code>0xDC69</code>.</li>
</ul>

<p>The two 16-bit code units for ð© are <code>0xD83D</code> and <code>0xDC69</code>, or the byte
sequence <code>0xD8 0x3D 0xDC 0x69</code>.</p>

<p><strong>Surrogate pairs</strong></p>

<p>We said that UTF-16 encodes all code points in Plane 0 using a single
16-bit code unit, except the range <code>U+D800</code> to <code>U+DFFF</code>. That particular
range is reserved in the Unicode standard for UTF-16 surrogate pairs, so
code points in that range are unassigned and will never be assigned.</p>

<p>If we review the way UTF-16 encodes code points in code units, a 16-bit
code unit can be either:</p>

<ul>
<li>A value in the range <code>0x0</code> to <code>0xFFFF</code>, except the reserved range
<code>0xD800</code> to <code>0xDFFF</code>. This value is a valid code point in Plane 0.</li>
<li>A value in the range <code>0xD800</code> to <code>0xDBFF</code>, which represents the
first 10 bits of a code point in another plane after subtracting
<code>0x10000</code> and adding <code>0xD800</code> to the first 10 bits</li>
<li>A value in the range <code>0xDC00</code> to <code>0xDFFF</code>, which represents the
remaining 10 bits of a code point in another plane after subtracting
<code>0x10000</code> and adding <code>0xDC00</code> to the last 10 bits.</li>
</ul>

<p>Note that these ranges are disjoint - a value can appear in only one of
them, so each 16-bit code unit can unambiguously be identified, in
isolation. For code points like ð©, encoded as two 16-bit code units,
the code units are called a <em>surrogate pair</em>. The first code unit, in
the range <code>0xD800</code> to <code>0xDBFF</code> is called the <em>high surrogate</em> while the
second code unit, in the range <code>0xDC00</code> to <code>0xDFFF</code> is called the <em>low
surrogate</em>.</p>

<p>Since the Unicode standard and UTF-16 encoding evolved together, the
range <code>0xD800</code> to <code>0xDFFF</code> needed by the surrogate pairs was reserved in
Plane 0 and the code points were kept unassigned. Without this, UTF-16
would have had trouble encoding a code point in that range as it would
become undistinguishable from a surrogate.</p>

<p>UTF-16 is the default encoding used by Windows, Java, the .NET runtime,
and JavaScript. Another popular way to encode text is UTF-8.</p>

<h2>UTF-8</h2>

<p>UTF-8 uses 8-bit code units, so it encodes code points using one to four
bytes. To recap, Unicode code points can be represented in 21 bits, as
their valid range is between <code>0x0</code> and <code>0x10FFFF</code>.</p>

<p>UTF-8 encodes code points as follows:</p>

<ul>
<li>Code points in the range <code>U+0000</code> to <code>U+007F</code> are represented with a
single byte with the 8th (most significant) bit being 0:
<code>0b0xxxxxxx</code>.</li>
<li>Code points in the range <code>U+0080</code> to <code>U+07FF</code> are represented with
two bytes. The first byte starts with the bits <code>0b110xxxxx</code>, the
second byte is <code>0x10xxxxxx</code>. Without the prefixes, there are 11 bits
used to encode the code point (count the number of <code>x</code>s ).</li>
<li>Code points in the range <code>U+0800</code> to <code>U+FFFF</code> are represented with
three bytes. The first byte starts with the prefix <code>0b1110xxxx</code>, the
following two bytes with <code>0b10xxxxxx</code>. This leaves 16 bits to encode
the code point.</li>
<li>Code points in the range <code>U+10000</code> to <code>U+10FFFF</code> are represented
with four bytes. The first byte starts with the prefix <code>0b11110xxx</code>,
the following three bytes with <code>0b10xxxxxx</code>. This leaves 21 bits to
encode the code point.</li>
</ul>

<p>This encoding has several interesting properties: for code points in
lower planes, it is more compact than UTF-16. UTF-16 requires either one
or two 16-bit code units, while UTF-8 can use 8, 16, 24, or 32 bits
depending on the code point. Commonly used alphabets are in the lower
planes, so usually fewer bits are needed.</p>

<p>UTF-8 is also ASCII-compatible: the first 128 characters (<code>U+0000</code> to
<code>U+007F</code>), represented in 7 bits, are the same as the old ASCII
encoding. An ASCII string can be used directly as UTF-8 encoded text
without any transformations required.</p>

<p>Unlike UTF-16, which can uniquely distinguish each code unit as either a
code point, a high surrogate, or a low surrogate, with UTF-8 we cannot
always determine what a code unit is in isolation: <code>0b10110011</code> could be
the second, third, or fourth byte in a code point. This is a consequence
of the more compact encoding. On the other hand, with UTF-8 we can look
at the bit prefix and determine the length of the sequence:</p>

<ul>
<li>If the prefix of the byte is <code>0b0xxxxxxx</code>, we have an ASCII
character.</li>
<li>If the prefix is <code>0b110xxxxx</code>, we are looking at the first byte of a
code point encoded in 2 bytes.</li>
<li>If the prefix is <code>0b1110xxxx</code>, we are expecting a sequence of 3
bytes.</li>
<li>If the prefix is <code>0b11110xxx</code>, we are expecting a sequence of 4
bytes.</li>
<li>If the prefix is <code>0b10xxxxxx</code>, we know we aren't looking at the
first byte in a sequence, rather at a byte inside a sequence.</li>
</ul>

<p>Note the bit patterns do not overlap. Beyond ASCII, the number of 1 bits
in the prefix coincides with the number of bytes used to encode the code
point.</p>

<p>As an example, let's take the same ð© emoji and see how its encoding
looks like in UTF-8. ð© is the code point <code>U+1F469</code>, so it requires 4
bytes. <code>0x1F469</code> represented in binary with 21 bits is
<code>0b000011111010001101001</code>.</p>

<p>We fill this into <code>0b11110xxx 0b10xxxxxx 0b10xxxxxx 0b10xxxxxx</code>, which
gives us <code>0b11110000 0b10011111 0b10010001 0b10101001</code>. In hexadecimal,
this is <code>0xF0 0x9F 0x91 0xA9</code>. This is the encoding of our emoji in
UTF-8.</p>

<p>UTF-8 is the default encoding used by Linux and macOS. It is also the
standard for the internet, with a majority of web pages using this
encoding.</p>

<p>Another important thing to keep in mind when manipulating text is how it
is encoded. When reading a sequence of bytes from a file or a network
connection, we need to make sure we don't mistakenly try to interpret
UTF-8 encoded text as UTF-16 encoded text or vice-versa. Since different
systems default to different encodings, this is a very plausible
scenario.</p>

<h2>Summary</h2>

<p>In this post we looked at some common text encoding standards and
concepts:</p>

<ul>
<li>ASCII, which encodes 128 characters.</li>
<li>Extended ASCII, which encodes 256 characters:

<ul>
<li>Code page 437, with box-drawing characters</li>
<li>The ISO/IEC 8859 16-part standard with code pages for various
alphabets</li>
</ul></li>
<li>Unicode:

<ul>
<li>Code points and planes</li>
<li>Graphemes and combining characters</li>
</ul></li>
<li>Encodings:

<ul>
<li>The inefficient UTF-32</li>
<li>UTF-16 and surrogate pairs</li>
<li>Popular UTF-8</li>
</ul></li>
</ul>
]]></description>
      <pubDate>Sun, 18 Nov 2018 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/10/13/arithmetic-overflow-and-underflow.html</link>
      <guid>https://vladris.com/blog/2018/10/13/arithmetic-overflow-and-underflow.html</guid>
      <title><![CDATA[Arithmetic Overflow and Underflow]]></title>
      <description><![CDATA[<h1>Arithmetic Overflow and Underflow</h1>

<p>Arithmetic overflow happens when an arithmetic operation results in a
value that is outside the range of values representable by the
expression's type. For example, the following C++ code prints <code>0</code>:</p>
<div class="highlight"><pre><span/><span class="kt">uint16_t</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">65535</span><span class="p">;</span>
<span class="n">x</span><span class="o">++</span><span class="p">;</span>

<span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
</pre></div>

<p><code>x</code> is an unsigned 16 bit integer, which can represent values between 0
and 65535. If <code>x</code> is 65535 and we increment it, the value becomes 65536
but that value cannot be represented by a <code>uint16_t</code>. This is an
overflow. In this case, C++ wraps the value around and <code>x</code> becomes 0.</p>

<p>Similarly, an underflow occurs when an arithmetic operation generates a
result that is below the smallest representable value of the
expression's type:</p>
<div class="highlight"><pre><span/><span class="kt">uint16_t</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="n">x</span><span class="o">--</span><span class="p">;</span>

<span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
</pre></div>

<p>The above prints 65535, as the result of decrementing 0 is -1, which
cannot be represented by an <code>uint16_t</code>.</p>

<p>Before we digging into overflow behavior, we need to understand how
computers represent numbers.</p>

<h2>Number Representations</h2>

<h3>Arbitrarily large integers</h3>

<p>Python provides support for arbitrarily large integers: unlike C++,
where the bit width (number of bits used to represent a number) is
fixed, we can have integers of any size:</p>
<div class="highlight"><pre><span/><span class="n">print</span><span class="p">(</span><span class="mi">10</span><span class="o">**</span><span class="mi">100</span><span class="p">)</span>
</pre></div>

<p>Prints</p>

<blockquote style="word-wrap:break-word">
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
</blockquote>

<p>Why don't all languages provide such support? The answer is
performance. The underlying hardware the code runs on uses fixed-width
integers, so performing arithmetic on fixed-width integer types becomes
a single CPU instruction. On the other hand, supporting arbitrarily
large integers usually involves writing code to determine how many bits
a given value or the result of an arithmetic operation needs and convert
that into an array of fixed-width integers large enough to hold that
value. The added overhead of this is non-trivial, so unlike Python, most
other mainstream languages offer only fixed-width integers and support
arbitrarily large integers only explicitly, via libraries.</p>

<h3>Unsigned integers</h3>

<p>Unsigned integers are represented as a sequence of <code>N</code> bits, thus being
able to represent numbers between 0 and 2<sup>N</sup>-1. An unsigned 8-bit
integer can store any value between 0 and 255, an unsigned 16-bit
integer can store any value between 0 and 65535, an unsigned 32-bit
integer between 0 and 4294967295, and an unsigned 64-bit integer between
0 and 18446744073709551615.</p>

<p>Unsigned integer representation is trivial.</p>

<h3>Signed integers</h3>

<p>Signed integers are usually represented in two's complement.</p>

<p>Positive numbers are encoded the same as unsigned binary numbers
described above. Negative numbers are encoded as two's complement of
their absolute value. For example, an 8-bit representation of -3 is
2<sup>8</sup>-3.</p>

<p>The most significant bit is always 1 for negative numbers and 0 for
positive numbers or 0.</p>

<p>With this representation, <code>N</code> bits can encode a signed integer between
2<sup>N-1</sup>-1 and -2<sup>N-1</sup>. So 8 bits can encode an integer
between -128 and 127.</p>

<h2>Handling Overflow</h2>

<p>If the result of an arithmetic operation cannot fit the type, there are
several approaches we can take and different programming languages
employ different strategies. These are:</p>

<ul>
<li>Exceptions</li>
<li>Wrap-around</li>
<li>Saturation</li>
</ul>

<p>All of these approaches have their pros and cons.</p>

<h3>Exceptions</h3>

<p>The safest approach is to treat an arithmetic overflow as an exception.
This usually gets rid of security vulnerabilities and treats any
overflow as an exceptional scenario. In this case an exception is thrown
(or an error returned) whenever an arithmetic operation overflows or
underflows.</p>

<p>This is usually desirable from a security/safety perspective, but the
trade-off is in performance: the downside of this approach is that all
arithmetic operations need to be checked for overflow (underlying
hardware usually does not do this natively) and exceptions need to be
handled by callers.</p>

<h3>Wrap-around</h3>

<p>The default behavior in C++, wrap-around simply continues from the
smallest possible value in case of overflow or from the largest possible
value in case of underflow. For unsigned integers, this is equivalent to
modulo arithmetic. For example, for an <code>int8_t</code>, which can represent
values between -128 and 127, wrap-around would make 127 + 1 be -128 and
similarly -128 - 1 be 127.</p>

<p>This is usually the most efficient way to perform arithmetic as no
checking is involved. Most hardware uses wrap-around as it can simply
discard overflowing bits to achieve the result. The two's complement
representation of 127 is <code>01111111</code>. The two's complement
representation of 128 is <code>10000000</code>. With this representation, adding 1
to 127 naturally makes it 128.</p>

<p>This is also the most unsafe implementation as it can lead to unexpected
behavior and exploitable security holes<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>.</p>

<h3>Saturation</h3>

<p>Saturation means clamping the value within the allowed range, so on
overflow, we would simply stop at the largest representable value. On
underflow, we would stop at the smallest representable value. In our
8-bit signed integer example, we would now have 127 + 1 be 127 and
-128 - 1 be -128. There are several advantages with this approach: for
one, the resulting values on overflow and underflow are the closest to
the <q>real</q> values we would get if operating without constraints. A lot
of physical systems naturally lend themselves to saturation. Imagine,
for example, a thermostat which can only operate within a range of
temperature.</p>

<p>The downsides of this approach are results which might be surprising and
the fact that properties of arithmetic operations like associativity no
longer hold: (120 + 10) + (-10) is 117, but 120 + (10 + (-10)) is 120.</p>

<h2>Detecting Overflow and Underflow</h2>

<p>Let's now see how we can tell whether an arithmetic operation overflow
while operating only within the range of values representable by a given
type.</p>

<p>For a type which can represent any value between some <code>MIN</code> and <code>MAX</code>,
we observe that an addition overflow means <code>a + b &gt; MAX</code>, while an
underflow means <code>a + b &lt; MIN</code> (note <code>a</code> and <code>b</code> can be negative, so
adding them could produce a value that would be under our minimum
representable value).</p>

<p>We can detect overflow and underflow by checking, if <code>b &gt;= 0</code>, that
<code>a &gt; MAX - b</code>, otherwise with <code>b &lt; 0</code>, that <code>a &lt; MIN - b</code>.</p>

<p>The reason this works is that, if <code>b</code> is greater than or equal to 0, we
can safely subtract it from <code>MAX</code> (if it were negative, subtracting it
would cause an overflow). So with this in mind, we are simply saying
that <code>a + b &gt; MAX</code> is equivalent to <code>a &gt; MAX - b</code> (subtracting <code>b</code> on
both sides). We also observe that <code>a + b</code> can never underflow if <code>b</code> is
greater than or equal to 0 because, regardless how small <code>a</code> is, adding
a positive number to it will make it larger not smaller.</p>

<p>If <code>b</code> is less than 0, then by the same logic we cannot possibly
overflow -regardless how large <code>a</code> is, adding <code>b</code> to it would make it
smaller. In this case we only need to check for underflow. Here we
observe that subtracting a negative number from <code>MIN</code> is safe - it will
increase <code>MIN</code>. So by subtracting <code>b</code> on both sides of <code>a + b &lt; MIN</code>, we
get <code>a &lt; MIN - b</code>.</p>

<p>The following code implements these two checks:</p>
<div class="highlight"><pre><span/><span class="cp">##include &lt;limits&gt;</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">AdditionOverflows</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">max</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">b</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">AdditionUnderflows</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">min</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Detecting overflow or underflow for subtraction is very similar, as
subtracting <code>b</code> from <code>a</code> is the equivalent of adding <code>-b</code> to <code>a</code>, thus
we only need to adjust the checks. <code>a - b &gt; MAX</code> means <code>a &gt; MAX + b</code> if
<code>b</code> is negative (so we don't cause an overflow during the check), while
<code>a - b &lt; MIN</code> means <code>a &lt; MIN + b</code> if <code>b</code> is greater than or equal to 0:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">SubtractionOverflows</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">max</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">b</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">SubtractionUnderflows</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="o">&gt;=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">min</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">b</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Detecting overflow for multiplication is more interesting. <code>a * b &gt; MAX</code>
can happen if <code>b &gt; 0</code>, <code>a &gt; 0</code>, and <code>a &gt; MAX / b</code> or when <code>b &lt; 0</code>,
<code>a &lt; 0</code>, and <code>a &lt; MAX / b</code> (dividing <code>a * b &gt; MAX</code> on both sides by <code>b</code>,
a negative number, flips the sign of the inequality).</p>

<p>Underflow can happen only when one of the numbers is negative and the
other one isn't. So if <code>b &gt; 0</code>, <code>a &lt; 0</code>, and <code>a &lt; MIN / b</code> or if
<code>b &lt; 0</code>, <code>a &gt; 0</code>, and <code>a &gt; MIN / b</code>.</p>

<p>We can implement the checks as follows:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">MultiplicationOverflows</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span><span class="w"> </span><span class="c1">// Avoid division by 0</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">((</span><span class="n">b</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">max</span><span class="p">()</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">b</span><span class="p">))</span>
<span class="w">        </span><span class="o">||</span><span class="w"> </span><span class="p">((</span><span class="n">b</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">max</span><span class="p">()</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">b</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">MultiplicationUnderflows</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span><span class="w"> </span><span class="c1">// Avoid division by 0</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">((</span><span class="n">b</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">min</span><span class="p">()</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">b</span><span class="p">))</span>
<span class="w">        </span><span class="o">||</span><span class="w"> </span><span class="p">((</span><span class="n">b</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">min</span><span class="p">()</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">b</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>Note integer division cannot possibly underflow. The single overflow
that can happen is due to the fact that in two's complement
representation, we can represent one more negative number than
positives, as 0 is, in a sense, positive with this representation (the
sign bit is not set for 0). An 8-bit signed integer can represent 128
positive values (0 to 127) and 128 negative values (-1 to -128).
Overflow can only happen when we change the sign of the smallest
possible value we can represent by dividing it with -1. -128 / -1
becomes 128, which is an overflow. This is the only case we need to
check for:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">constexpr</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">DivisionOverflows</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">min</span><span class="p">())</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">b</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">-1</span><span class="p">)</span>
<span class="w">        </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Note that unsigned integers can never overflow, so once we confirm that
<code>a</code> is the smallest possible value and <code>b</code> is -1, we also check to
ensure <code>a</code> is not <code>0</code>.</p>

<p>We are explicitly not looking at division by 0, which is part of the
same safe arithmetic topic. This post focuses on overflow and underflow
only.</p>

<h2>Handling Overflow and Underflow</h2>

<p>Now that we can detect overflows and underflows, we can implement a
couple of policies to handle them. Wrap-around is the default behavior
in C++, so let's look at the other two possibilities. We will implement
a couple of types templated on an integer type <code>T</code>, with overflow and
underflow handlers:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Policy</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">OnOverflow</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">OnUnderflow</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>The throwing policy looks like this:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">ArithmeticException</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">exception</span><span class="w"> </span><span class="p">{};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">ArithmeticOverflowException</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">ArithmeticException</span><span class="w"> </span><span class="p">{};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">ArithmeticUnderflowException</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">ArithmeticException</span><span class="w"> </span><span class="p">{};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">ThrowingPolicy</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">OnOverflow</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArithmeticOverflowException</span><span class="p">{};</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">OnUnderflow</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ArithmeticUnderflowException</span><span class="p">{};</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>The saturation policy is:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">SaturationPolicy</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">OnOverflow</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">max</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="nf">OnUnderflow</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">numeric_limits</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">min</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<h2>Safe Arithmetic</h2>

<p>Now that we have all the required pieces, we can create a type that
wraps an integer type and implements all the arithmetic operations
checking for overflow or underflow. The type is templated on a policy
for handling overflows and underflows:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="o">&gt;</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Policy</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">Integer</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>

<span class="w">    </span><span class="k">constexpr</span><span class="w"> </span><span class="n">Integer</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Policy</span><span class="o">&gt;</span><span class="w"> </span><span class="k">operator</span><span class="o">+</span><span class="p">(</span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">Integer</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Policy</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">other</span><span class="p">)</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">AdditionOverflows</span><span class="p">(</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Policy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">OnOverflow</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">AdditionUnderflows</span><span class="p">(</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Policy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">OnUnderflow</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="p">};</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">constexpr</span><span class="w"> </span><span class="n">Integer</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Policy</span><span class="o">&gt;</span><span class="w"> </span><span class="k">operator</span><span class="o">-</span><span class="p">(</span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">Integer</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Policy</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">other</span><span class="p">)</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">SubtractionOverflows</span><span class="p">(</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Policy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">OnOverflow</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">SubtractionUnderflows</span><span class="p">(</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Policy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">OnUnderflow</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="p">};</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">constexpr</span><span class="w"> </span><span class="n">Integer</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Policy</span><span class="o">&gt;</span><span class="w"> </span><span class="k">operator</span><span class="o">*</span><span class="p">(</span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">Integer</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Policy</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">other</span><span class="p">)</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">MultiplicationOverflows</span><span class="p">(</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Policy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">OnOverflow</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">MultiplicationUnderflows</span><span class="p">(</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Policy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">OnUnderflow</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="p">};</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">constexpr</span><span class="w"> </span><span class="n">Integer</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Policy</span><span class="o">&gt;</span><span class="w"> </span><span class="k">operator</span><span class="o">/</span><span class="p">(</span>
<span class="w">        </span><span class="k">const</span><span class="w"> </span><span class="n">Integer</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Policy</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">other</span><span class="p">)</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">DivisionOverflows</span><span class="p">(</span><span class="n">value</span><span class="p">,</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Policy</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">OnOverflow</span><span class="p">();</span><span class="w"> </span><span class="p">}</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="p">};</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>Now we can wrap an integer type with this and perform safe arithmetic:</p>
<div class="highlight"><pre><span/><span class="n">Integer</span><span class="o">&lt;</span><span class="kt">int8_t</span><span class="p">,</span><span class="w"> </span><span class="n">ThrowingPolicy</span><span class="o">&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">{</span><span class="w"> </span><span class="mi">64</span><span class="w"> </span><span class="p">};</span>
<span class="n">Integer</span><span class="o">&lt;</span><span class="kt">int8_t</span><span class="p">,</span><span class="w"> </span><span class="n">ThrowingPolicy</span><span class="o">&gt;</span><span class="w"> </span><span class="n">b</span><span class="p">{</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="p">};</span>

<span class="c1">// Throws</span>
<span class="n">Integer</span><span class="o">&lt;</span><span class="kt">int8_t</span><span class="p">,</span><span class="w"> </span><span class="n">ThrowingPolicy</span><span class="o">&gt;</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">;</span>
</pre></div>

<p>This is a simple implementation for illustrative purposes. The <code>Integer</code>
type currently only defines addition, subtraction, multiplication, and
division. A complete implementation would handle multiple other
operators, like pre and post increment, implicit casting from <code>T</code> etc.</p>

<p>The generic overflow and underflow checks can be specialized for
unsigned types so that we don't redundantly check for <code>b &lt; 0</code> for a
type which cannot represent negative numbers. Similarly, we wouldn't
worry, for example, about addition underflowing for an unsigned type.</p>

<p>We can also extend our safe arithmetic to not only rely on the standard
<code>numeric_limits</code>, but also allow users to clamp values between
user-defined minimum and maximum values.</p>

<p>For a production-ready safe arithmetic library, I recommend you check
out David LeBlanc's <a href="https://github.com/dcleblanc/SafeInt">SafeInt</a>.</p>

<h2>Summary</h2>

<p>This post covered arithmetic overflow and underflow, and ways to handle
it. We looked at:</p>

<ul>
<li>What arithmetic overflow and underflow are.</li>
<li>Integer representations:

<ul>
<li>Unsigned</li>
<li>Two's complement</li>
</ul></li>
<li>Ways to deal with overflow/underflow:

<ul>
<li>Exceptions</li>
<li>Wrap-around</li>
<li>Saturation</li>
</ul></li>
<li>How to detect overflow/underflow.</li>
<li>Implementing a simple <code>Integer</code> wrapper that performs safe
arithmetic.</li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>An example of how an attacker can exploit integer overflow is the
following <a href="https://www.kb.cert.org/vuls/id/945216">SSH1
vulnerability</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sat, 13 Oct 2018 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/09/09/clean-code-types.html</link>
      <guid>https://vladris.com/blog/2018/09/09/clean-code-types.html</guid>
      <title><![CDATA[Clean Code: Types]]></title>
      <description><![CDATA[<h1>Clean Code: Types</h1>

<p>I recently revived my Clean Code tech talk which I put together a couple
of years ago and with which I started this blog: <a href="https://vladris.com/blog/2016/01/04/clean-code-part-1.html">Clean Code - Part
1</a> and
<a href="https://vladris.com/blog/2016/01/07/clean-code-part-2.html">Clean Code - Part
2</a>. I took
the opportunity to completely revamp the talk and ended up with 3 parts:
<em>Algorithms</em>, <em>Types</em>, and <em>State</em>. The <em>Algorithms</em> is mostly covered
by the <a href="https://vladris.com/blog/2018/02/11/fibonacci.html">Fibonacci</a>
post, so in this post we will talk about <em>Types</em>.</p>

<h2>Mars Climate Orbiter</h2>

<p>The Mars Climate Orbiter crashed and disintegrated in the Mars
atmosphere because a component developed by Lockheed provided momentum
measured in pound-force seconds, while another component developed by
NASA expected momentum as Newton seconds.</p>

<p>We can image the component developed by NASA being something like this:</p>
<div class="highlight"><pre><span/><span class="c1">// Will not disintegrate as long as momentum &gt;= 2 N s</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">trajectory_correction</span><span class="p">(</span><span class="kt">double</span><span class="w"> </span><span class="n">momentum</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">momentum</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="cm">/* N s */</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">disintegrate</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="cm">/* ... */</span>
<span class="p">}</span>
</pre></div>

<p>We can also imagine the Lockheed component calling into the above with:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">trajectory_correction</span><span class="p">(</span><span class="mf">1.5</span><span class="w"> </span><span class="cm">/* lbf s */</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>A pound-force second (lbfs) is about 4.448222 Newton seconds (Ns). So
from Lockheed's perspective, passing in 1.5 lbfs to
<code>trajectory_correction</code> should be just fine: 1.5 lbfs is about 6.672333
Ns, way above the 2 Ns threshold.</p>

<p>The problem is the interpretation of the data. The NASA component ends
up comparing lbfs to Ns without conversion, misinterpreting the lbfs
input as Ns. Since 1.5 is less than 2, the orbiter disintegrates. This
is a known anti-pattern called <q>primitive obsession</q>.</p>

<h2>Primitive Obsession</h2>

<p>Primitive obsession happens when we use a primitive data type to
represent a value in the problem's domain and causes situations like
the above. Representing zip codes as numbers, telephone numbers as
strings, Ns and lbfs as <code>double</code> are all examples of this.</p>

<p>A more type safe solution would have defined a simple <code>Ns</code> type:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Ns</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">double</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">bool</span><span class="w"> </span><span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Ns</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">Ns</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">b</span><span class="p">.</span><span class="n">value</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>We can similarly define a simple <code>lbfs</code> type:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">lbfs</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">double</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">bool</span><span class="w"> </span><span class="k">operator</span><span class="o">&lt;</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">lbfs</span><span class="o">&amp;</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">lbfs</span><span class="o">&amp;</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="p">.</span><span class="n">value</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">b</span><span class="p">.</span><span class="n">value</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Now we can implement a type safe <code>trajectory_correction</code>:</p>
<div class="highlight"><pre><span/><span class="c1">// Will not disintegrate as long as momentum &gt;= 2 N s</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">trajectory_correction</span><span class="p">(</span><span class="n">Ns</span><span class="w"> </span><span class="n">momentum</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">momentum</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">Ns</span><span class="p">{</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="p">})</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">disintegrate</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="cm">/* ... */</span>
<span class="p">}</span>
</pre></div>

<p>Calling this with <code>lbfs</code> as below fails to compile as the types are
incompatible:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">trajectory_correction</span><span class="p">(</span><span class="n">lbfs</span><span class="p">{</span><span class="w"> </span><span class="mf">1.5</span><span class="w"> </span><span class="p">});</span>
<span class="p">}</span>
</pre></div>

<p>Note how the meaning of the values, which used to be specified in
comments (<code>2 /* Ns */</code>, <code>/* lbfs */</code>) gets pulled into the type system
and expressed in code (<code>Ns{ 2 }</code>, <code>lbfs{ 1.5 }</code>).</p>

<p>We can, of course, provide casting from <code>lbfs</code> to <code>Ns</code> as an explicit
operator:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">lbfs</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">double</span><span class="w"> </span><span class="n">value</span><span class="p">;</span>

<span class="w">    </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Ns</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">value</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="mf">4.448222</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>Equipped with this, we can call <code>trajectory_correction</code> via a static
cast:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">trajectory_correction</span><span class="p">(</span><span class="k">static_cast</span><span class="o">&lt;</span><span class="n">Ns</span><span class="o">&gt;</span><span class="p">(</span><span class="n">lbfs</span><span class="p">{</span><span class="w"> </span><span class="mf">1.5</span><span class="w"> </span><span class="p">}));</span>
<span class="p">}</span>
</pre></div>

<p>This does the right thing of multiplying by the ratio. The cast can also
be made implicit (by using the <code>implicit</code> keyword instead), in which
case it is applied automatically. As a rule of thumb, it's best to
follow the Zen of Python:</p>

<blockquote>
<p>Explicit is better than implicit</p>
</blockquote>

<p>The moral of the story is that nowadays we have very sophisticated type
checkers but we do need to provide them enough information to catch this
type of errors. That information comes from declaring types to represent
our problem domain. <sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup></p>

<h2>State Space</h2>

<p>Bad things happen when our programs end up in a <em>bad state</em>. Types help
us narrow down the possibility of such bad states. One way to think
about this is to look at types as sets of possible values. For example
<code>bool</code> is the set <code>{true, false}</code> where a variable of the type can be
one of the two values. Similarly, <code>uint32_t</code> is the set
<code>{0 ... 4294967295}</code>. Looking at types like this, we can define the
<em>state space</em> of our program as the product of the types of all live
variables at a given point in time.</p>

<p>If we have a <code>bool</code> and an <code>uint32_t</code>, our state space is
<code>{true, false} X {0 ... 4294967295}</code>. This simply means that the two
variables can be in any of their possible states and since we have two
of them, our program can be in any of their combined states.</p>

<p>This gets more interesting when we look at functions that initialize
values:</p>
<div class="highlight"><pre><span/><span class="kt">bool</span><span class="w"> </span><span class="nf">get_momentum</span><span class="p">(</span><span class="n">Ns</span><span class="o">&amp;</span><span class="w"> </span><span class="n">momentum</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">some_condition</span><span class="p">())</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span>

<span class="w">    </span><span class="n">momentum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Ns</span><span class="p">{</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">};</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>In the above example we take a <code>Ns</code> by reference and initialize it if
some condition is met. The function returns <code>true</code> if the value was
properly initialized. If the function cannot, for whatever reason, set
the value, it returns <code>false</code>.</p>

<p>Looking at this from the state space lens, our state space is the
product <code>bool X Ns</code>. If the function returns <code>true</code>, then <code>momentum</code> was
set and is in any one of the possible <code>Ns</code> values. The problem is that
if the function returns <code>false</code>, then <code>momentum</code> was not set. It is
still in any one of the possible <code>Ns</code> values, but it is not a valid
value. Often times we have bugs where we accidentally propagate such
invalid state:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">example</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Ns</span><span class="w"> </span><span class="n">momenum</span><span class="p">;</span>

<span class="w">    </span><span class="n">get_momentum</span><span class="p">(</span><span class="n">momentum</span><span class="p">);</span>

<span class="w">    </span><span class="n">trajectory_correction</span><span class="p">(</span><span class="n">momentum</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>What we should have done instead is:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">example</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Ns</span><span class="w"> </span><span class="n">momentum</span><span class="p">;</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">get_momentum</span><span class="p">(</span><span class="n">momentum</span><span class="p">))</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">trajectory_correction</span><span class="p">(</span><span class="n">momentum</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>There is a better way though, where this can be enforced:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">Ns</span><span class="o">&gt;</span><span class="w"> </span><span class="n">get_momentum</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">some_condition</span><span class="p">())</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">nullopt</span><span class="p">;</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_optional</span><span class="p">(</span><span class="n">Ns</span><span class="p">{</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">});</span>
<span class="p">}</span>
</pre></div>

<p>Using an <code>optional</code>, this version of the function has a significantly
smaller state space: instead of <code>bool X Ns</code>, we have <code>Ns + 1</code>. The
function either returns a valid <code>Ns</code> value or <code>nullopt</code> to denote the
absence of a value. Now it becomes impossible to have an invalid <code>Ns</code>
that gets propagated throughout the system. We can also no longer
<em>forget</em> to check the return value as an <code>optional&lt;Ns&gt;</code> is not
implicitly convertible to an <code>Ns</code> - we need to explicitly unpack it:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">example</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">maybeMomentum</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">get_momentum</span><span class="p">();</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">maybeMomentum</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">trajectory_correction</span><span class="p">(</span><span class="o">*</span><span class="n">maybeMomentum</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>In general, we want our functions to return <strong>result or error</strong> not
<strong>result and error</strong>. This way we eliminate the states in which we have
an error but also an invalid result which might make its way in further
computation.</p>

<p>From this point of view, throwing exceptions is OK as this follows the
same pattern: a function either returns a result <strong>or</strong> throws an
exception.</p>

<h2>RAII</h2>

<p>RAII stands for <em>Resource Acquisition Is Initialization</em> but has more to
do with releasing resources. The name originated from C++ but the
pattern can be implemented in any language (see, for example, .NET's
<code>IDisposable</code>). RAII ensures automatic cleanup of resources.</p>

<p>What are resources? A few examples: heap memory, database connections,
OS handles. In general, a resource is something we acquire from the
outside world and we need to release when it is no longer needed. That
means executing some form of free, delete, close etc. on the resource.</p>

<p>Since these resources are external, they are not directly expressed into
our type system. For example if we allocate some heap memory, we get a
pointer on which we have to call <code>delete</code>:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span><span class="w"> </span><span class="p">{};</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">example</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Foo</span><span class="o">*</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Foo</span><span class="p">();</span>

<span class="w">    </span><span class="cm">/* Use foo */</span>

<span class="w">    </span><span class="k">delete</span><span class="w"> </span><span class="n">foo</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>But what happens if we forget or something prevents us from calling
<code>delete</code>?</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">example</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Foo</span><span class="o">*</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Foo</span><span class="p">();</span>

<span class="w">    </span><span class="k">throw</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">exception</span><span class="p">();</span>

<span class="w">    </span><span class="k">delete</span><span class="w"> </span><span class="n">foo</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>In this case we no longer call <code>delete</code> and we leak the resource. In
general, we don't want to perform such manual cleanup. For heap memory,
we actually have <code>unique_ptr</code> to help us manage it:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">example</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">throw</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">exception</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>The <code>unique_ptr</code> is a stack object so whenever it goes out of scope
(when the function throws or during stack unwinding if an exception was
thrown) its destructor gets called. It's destructor implements the call
to <code>delete</code>. This way, we no longer have to manually manage the memory
resource - we hand it off to a wrapper which owns it and handles
releasing it.</p>

<p>Similar wrappers exist or can be created for any of the other resources
(for example a Windows OS <code>HANDLE</code> can be wrapped in a type where its
destructor would call <code>CloseHandle</code>.</p>

<p>The key takeaway is never to do manual resource cleanup - either use an
existing wrapper or, if none exists for your particular scenario,
implement one.</p>

<h2>Summary</h2>

<p>This post started with a famous example of why typing is important, and
covered three important aspects of leveraging types to write safer code:</p>

<ul>
<li>Declaring and using stronger types (as opposed to primitive
obsession).</li>
<li>Reducing state space, returning result or error instead of result
and error.</li>
<li>RAII and automatic resource management.</li>
</ul>

<p>Types are great tools for implementing safer, reusable code.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>There is a great series of posts on Fluent C++ on <a href="https://www.fluentcpp.com/category/strong-types/">Strong
Typing</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sun, 09 Sep 2018 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/07/16/implementing-a-variant-type-in-csharp.html</link>
      <guid>https://vladris.com/blog/2018/07/16/implementing-a-variant-type-in-csharp.html</guid>
      <title><![CDATA[Implementing a Variant Type in C#]]></title>
      <description><![CDATA[<h1>Implementing a Variant Type in C#</h1>

<p>A variant, or discriminated union type<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>, is a type that can hold a
value of any of a finite set of types. For example, a
<code>Variant&lt;int, string&gt;</code> can hold either an <code>int</code> or a <code>string</code> value.
This is also known as a <em>sum type</em>, as its domain is the sum of the
<code>int</code> and <code>string</code> domains. Contrast this with a <code>Tuple&lt;int, string&gt;</code>,
also known as a <em>product type</em>, which holds <em>both</em> an <code>int</code> and a
<code>string</code> (so its domain is the product of the <code>int</code> and <code>string</code>
domains).</p>

<p>First, let's look at how something like this would be achieved without a
<code>Variant</code> type. Let's take an expression tree where a node can be either
an <code>int</code> value or an expression consisting of an operation (let's say
addition and multiplication) and two operands which are in turn nodes.
We could implement this by starting with an <code>INode</code> base interface and
deriving our types from that:</p>
<div class="highlight"><pre><span/><span class="k">enum</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Add</span><span class="p">,</span><span class="w"> </span><span class="n">Mul</span><span class="w"> </span><span class="p">}</span>

<span class="k">interface</span><span class="w"> </span><span class="n">INode</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="k">class</span><span class="w"> </span><span class="nc">ExpressionNode</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">INode</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">INode</span><span class="w"> </span><span class="n">Left</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">INode</span><span class="w"> </span><span class="n">Right</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>

<span class="k">class</span><span class="w"> </span><span class="nc">ValueNode</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">INode</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">Value</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This works, but has a couple of drawbacks -- first, to discriminate
between the types allowed to be part of the tree and the types that
aren't, we need to establish a typing relationship and force every type
of node in our tree to implement a dummy <code>INode</code> interface. In the case
of a value, even though we just need an <code>int</code>, we must wrap it into a
<code>ValueNode</code> class because <code>int</code> itself does not implement <code>INode</code>.</p>

<p>Another drawback is that in many cases we want to restrict the types
that can participate in our system (in this case our expression tree).
This is harder to enforce via an interface, as one could always
implement some other <code>class FooNode : INode</code> and there is no
compile-time way to prevent this node from becoming part of our tree.</p>

<p>This is how the above tree would be declared if we had a
<code>Variant&lt;T1, T2&gt;</code>:</p>
<div class="highlight"><pre><span/><span class="k">enum</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">Add</span><span class="p">,</span><span class="w"> </span><span class="n">Mul</span><span class="w"> </span><span class="p">}</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Expression</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="n">Op</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">Expression</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Left</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">Expression</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Right</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>First, we no longer need an <code>INode</code>, as it would get replaced by
<code>Variant&lt;Expression, int&gt;</code>, which effectively translates to <em>it's either
an Expression or an int</em>. There is also no room to sneak in another type
without being explicit about it. We do not need to wrap <code>int</code> into
another class either just to make it conform to our hierarchy, as a
<code>Variant</code> can handle it directly.</p>

<p>So how would we go about designing such a generic variant in C#?</p>

<h2>Design Considerations</h2>

<p>Our variant implementation should satisfy a few requirements:</p>

<ul>
<li><p>Since C# does not support variadic generic arguments, we want
implementations from <code>Variant&lt;T1&gt;</code>, holding a value of a single
type, up to <code>Variant&lt;T1, T2, T3, T4, T5, T6, T7, T8&gt;</code>, holding a
value of any of 8 types. This is in line with how other library
types like <code>Tuple</code> are implemented.</p></li>
<li><p>We want to support implicit casting from one of the generic types to
the variant, as this enables assignment:</p>
<div class="highlight"><pre><span/><span class="n">Variant</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span>
</pre></div></li>
<li><p>We want to support explicit casting from a variant to any of its
generic types. Since a variant might hold a value of a different
type, we should be explicit in this case, as a mismatch between the
actual held value and the cast-to type would throw an
<code>InvalidCastException</code>.</p></li>
<li><p>We need an API to get the value of the variant as a given type. A
type mismatch between the given type and the one actually held by
the variant would result in an <code>InvalidCastException</code>:</p>
<div class="highlight"><pre><span/><span class="n">Variant</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span>

<span class="kt">int</span><span class="w"> </span><span class="k">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">();</span>
<span class="kt">string</span><span class="w"> </span><span class="k">value</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="p">();</span><span class="w"> </span><span class="c1">// throws InvalidCastException</span>
</pre></div></li>
<li><p>We need an API to check if the value of the variant is of a certain
type:</p>
<div class="highlight"><pre><span/><span class="n">Variant</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span>

<span class="n">variant</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="kt">string</span><span class="o">&gt;</span><span class="p">();</span><span class="w"> </span><span class="c1">// false</span>
<span class="n">variant</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">();</span><span class="w"> </span><span class="c1">// true</span>
</pre></div></li>
<li><p>We need to support variants where the same type appears several
times, like <code>Variant&lt;int, int&gt;</code>. There are legitimate use cases for
this, for example an API that would return either an error code or a
value, both being of the same type. For such cases, we need another
way to explicitly set a value as the first, second, and so on type,
and an <code>Index</code> property that would tell us which occurrence of the
type it is (as <code>Get&lt;int&gt;()</code> called on a <code>Variant&lt;int, int&gt;</code> would
succeed in returning us an <code>int</code>, but we wouldn't be able to tell
whether it got in there as a <code>T1</code> or as a <code>T2</code>.</p></li>
<li><p>We would also provide a non-generic <code>Get()</code> which returns an
<code>object</code>, so we can use pattern matching on a variant:</p>
<div class="highlight"><pre><span/><span class="n">Variant</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span>

<span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="p">())</span>
<span class="p">{</span>
<span class="w">  </span><span class="k">case</span><span class="w"> </span><span class="kt">string</span><span class="w"> </span><span class="n">s</span><span class="p">:</span>
<span class="w">      </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">"It's a string: "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">s</span><span class="p">);</span>
<span class="w">      </span><span class="k">break</span><span class="p">;</span>
<span class="w">  </span><span class="k">case</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">:</span>
<span class="w">      </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="s">"It's an int: "</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">i</span><span class="p">);</span>
<span class="w">      </span><span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
</pre></div></li>
<li><p>We need to override equality: two variants are equivalent if they
are the same type (same generic parameters), they contain values of
the same type at the same index, and the contained values are
equivalent:</p>
<div class="highlight"><pre><span/><span class="n">Variant</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">variant1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span>
<span class="n">Variant</span><span class="o">&lt;</span><span class="kt">string</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">variant2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span>

<span class="n">variant1</span><span class="p">.</span><span class="n">Equals</span><span class="p">(</span><span class="n">variant2</span><span class="p">);</span><span class="w"> </span><span class="c1">// true</span>
</pre></div></li>
</ul>

<p>Given these requirements, let's see how an implementation would look
like.</p>

<h2>Implementation</h2>

<h3>API</h3>

<p>We'll start with a <code>Variant&lt;T1, T2&gt;</code> and build up from there. Adding
more generic arguments becomes easy once this implementation is figured
out. Starting from the simpler <code>Variant&lt;T1&gt;</code> would not uncover some of
the issues mentioned above, like the need for an index and ability to
handle <code>T1</code> and <code>T2</code> being the same type. Let's define our API based on
the requirements:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Variant API</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">Index</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="c1">// T1 constructor, casts</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T1</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="c1">// T2 constructor, casts</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T2</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="c1">// Equality</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="nf">Equals</span><span class="p">(</span><span class="kt">object</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">GetHashCode</span><span class="p">()</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NotImplementedException</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>We have the <code>Index</code> property which should be <code>0</code> if the variant is
holding a <code>T1</code> and <code>1</code> if the variant is holding a <code>T2</code>. We're using
0-based indexing for this, though it is a bit awkward that generic
arguments start, by convention, from 1. This is in line with what other
.NET types do, for example <code>Tuple</code> provides a 0-based indexer.</p>

<p><code>It&lt;T&gt;()</code> allows callers to check if the variant is currently holding a
<code>T</code>, while <code>Get&lt;T&gt;()</code> should return a <code>T</code> or throw an
<code>InvalidCastException</code>. The non-generic version <code>Get()</code> simply returns
an <code>object</code>.</p>

<p>Below that, for both <code>T1</code> and <code>T2</code> we provide a constructor which takes
a <code>T1</code> (or <code>T2</code>) and places it in the variant, implicit casts from <code>T1</code>
and <code>T2</code> to <code>Variant&lt;T1, T2&gt;</code>, and explicit casts the other way around.</p>

<p>Finally, we override <code>Equals(object)</code> and <code>GetHashCode()</code> (it's always a
good idea to override <code>GetHashCode</code> when overriding <code>Equals</code>).</p>

<h3>Type erasure</h3>

<p>Let's look at how we would store a value. Unlike a <code>Tuple&lt;T1, T2&gt;</code>, we
don't want to store both a <code>T1</code> <em>and</em> a <code>T2</code>, rather we want either a
<code>T1</code> <em>or</em> a <code>T2</code>. In order to generalize this, we need a way to perform
type-erasure, which means a way to store any type (as we want a generic
implementation), while at the same type we need to keep track of the
stored type so we can answer <code>Is&lt;T&gt;()</code> properly. Let's create a
<code>VariantHolder</code> to handle this.</p>

<p>We could achieve this by storing everything as an <code>object</code>
(type-erasure) and a <code>Type</code> (for type information), like this:</p>
<div class="highlight"><pre><span/><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">VariantHolder</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="n">Item</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="n">Type</span><span class="w"> </span><span class="n">_itemType</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">_itemType</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Item</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">VariantHolder</span><span class="p">(</span><span class="kt">object</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">Item</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">        </span><span class="n">_itemType</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">GetType</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>We can then implement our variant in terms of this:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="n">VariantHolder</span><span class="w"> </span><span class="n">variant</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">T</span><span class="p">)</span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T1</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="cm">/* ...</span>
<span class="cm">       Same for T2, ignoring Equals() and GetHashCode() for now */</span>
<span class="p">}</span>
</pre></div>

<p>This implementation is not quite correct, as it stores too much type
information:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Base</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Derived</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">Base</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="cm">/* ... */</span>

<span class="n">Variant</span><span class="o">&lt;</span><span class="n">Base</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Derived</span><span class="p">();</span>
<span class="n">variant</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="n">Base</span><span class="o">&gt;</span><span class="p">();</span><span class="w"> </span><span class="c1">// == false!</span>
</pre></div>

<p>We are comparing the actual type of the item, though we should store it
as one of the generic types of the variant declaration. A better idea is
to make our <code>VariantHolder</code> itself generic:</p>
<div class="highlight"><pre><span/><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">VariantHolder</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Item</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">U</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Item</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">VariantHolder</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">item</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Item</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This gets us rid of the extra <code>_itemType</code> member (we can use <code>typeof(T)</code>
on the generic parameter), but we have another problem: how do we
declare this in our <code>Variant</code>? If we make it a <code>VariantHolder&lt;T1&gt;</code>, then
we won't be able to store a <code>T2</code> value and vice-versa. There is a way
around this - we can extract an interface:</p>
<div class="highlight"><pre><span/><span class="k">interface</span><span class="w"> </span><span class="n">IVariantHolder</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>We can declare that our <code>VariantHolder&lt;T&gt;</code> implements this interface (it
already does, as it has both a generic <code>Is</code> and a non-generic <code>Get</code>:</p>
<div class="highlight"><pre><span/><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">VariantHolder</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">IVariantHolder</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Item</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">U</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">U</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Item</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">VariantHolder</span><span class="p">(</span><span class="n">T</span><span class="w"> </span><span class="n">item</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Item</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>And now we can implement our <code>Variant</code> in terms of an <code>IVariantHolder</code>:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">variant</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">((</span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">)</span><span class="n">variant</span><span class="p">).</span><span class="n">Item</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="p">();</span>

<span class="w">    </span><span class="c1">// T1 constructor, casts</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T1</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="c1">// T2 constructor, casts</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T2</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="cm">/* ...</span>
<span class="cm">       Ignoring Equals() and GetHashCode() for now */</span>
<span class="p">}</span>
</pre></div>

<p>For <code>Get&lt;T&gt;()</code> we use a cast to <code>VariantHolder&lt;T&gt;</code> as opposed to
<code>(T)_variantHolder.Get()</code> as this avoids an extra boxing operation if
<code>T</code> is a value type. This correctly throws <code>InvalidCastException</code> if
called with the wrong type. If we wanted to throw a different exception
or add more details to the exception, we could either wrap this cast in
a try/catch and catch an <code>InvalidCastException</code> or we could check the
type using <code>Is&lt;T&gt;()</code> before performing the cast.</p>

<h3>Index and disambiguation</h3>

<p>The only problem with this implementation is that we cannot instantiate
a variant if <code>T1</code> and <code>T2</code> are the same:</p>
<div class="highlight"><pre><span/><span class="n">Variant</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span>
</pre></div>

<p>yields a compiler error: <q>Ambiguous user defined conversions</q>. If we
try calling the constructor:</p>
<div class="highlight"><pre><span/><span class="kt">var</span><span class="w"> </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="mi">42</span><span class="p">);</span>
</pre></div>

<p>we get <q>The call is ambiguous between the following methods...</q>. If
<code>T1</code> and <code>T2</code> are the same type, there is no way to disambiguate between
constructors and casts. Because of this, we need to add our <code>Index</code>
property and provide a way to explicitly construct the variant with an
index. First, let's add <code>Index</code> to our current implementation:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">variant</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">Index</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">((</span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">)</span><span class="n">variant</span><span class="p">).</span><span class="n">Item</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="p">();</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">item</span><span class="p">,</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">index</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">        </span><span class="n">Index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">index</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="k">this</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T1</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="k">this</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T2</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="cm">/* ...</span>
<span class="cm">       Ignoring Equals() and GetHashCode() for now */</span>
<span class="p">}</span>
</pre></div>

<p>We added a read-only <code>Index</code> property, a private constructor that not
only sets the <code>IVariantHolder</code> but also the <code>Index</code>, and we updated our
two constructors, <code>Variant(T1 item)</code> and <code>Variant(T2 item)</code> to
internally call this private constructor with the correct index.</p>

<p>Now we have an <code>Index</code> property which accurately keeps track of the
index of the type stored, so for a <code>Variant&lt;int, int&gt;</code> we would be able
to tell whether we set the first or second <code>int</code>, but we still can't
disambiguate between constructor calls if <code>T1</code> and <code>T2</code> are the same. We
can solve this by adding a couple of explicit factory methods:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Make1</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">    </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>

<span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Make2</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">    </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
</pre></div>

<p>We could have provided a way for the callers to explicitly provide an
index, but it becomes hard to enforce that the index is in sync with the
type. If <code>T1</code> and <code>T2</code> are the same, then the caller ultimately decides
the index, but if <code>T1</code> and <code>T2</code> are different, then <code>Variant</code> needs to
decide the index.</p>

<p>Providing <code>Make1</code> and <code>Make2</code> works, since <code>Make1</code> only accepts a <code>T1</code>
argument while <code>Make2</code> only accepts a <code>T2</code> argument. Thus, if they are
the same, the caller disambiguates by calling one of the methods and
there is no compilation issue. If they are different, calling one of
them is the equivalent of calling one of the constructors (there is no
way to call <code>Make1</code> with a <code>T2</code> argument).</p>

<h3>Equality</h3>

<p>Now the only remaining bit is overriding <code>Equals</code>, as we want two
variants containing equivalent values to be equivalent. In other words,
given another object, we would consider it equivalent if it has the same
type as this object, has the value <em>at the same index</em>, and the value of
the other object is equivalent to the value of this object:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="nf">Equals</span><span class="p">(</span><span class="kt">object</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">obj</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">null</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="n">obj</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">))</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">false</span><span class="p">;</span>

<span class="w">    </span><span class="kt">var</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">)</span><span class="n">obj</span><span class="p">;</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">Index</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">Index</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">Get</span><span class="p">().</span><span class="n">Equals</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">Get</span><span class="p">());</span>
<span class="p">}</span>
</pre></div>

<p>Overriding <code>Equals</code> usually means overriding <code>GetHashCode</code> in such a way
that equivalent objects hash to the same value. In our case, we can rely
on the value stored in the variant to implement this by simply
delegating hashing to it:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">GetHashCode</span><span class="p">()</span>
<span class="w">    </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Get</span><span class="p">().</span><span class="n">GetHashCode</span><span class="p">();</span>
</pre></div>

<h3>Multiple generic arguments</h3>

<p>We have an implementation for a <code>Variant&lt;T1, T2&gt;</code> but we are looking at
providing variants from <code>Variant&lt;T1&gt;</code> all the way to
<code>Variant&lt;T1, T2, T3, T4, T5, T6, T7, T8&gt;</code>.</p>

<p>First, let's look at what would be common to all of these. The API
(<code>Is&lt;T&gt;</code>, <code>Get&lt;T&gt;</code> etc.) is implemented in terms of <code>IVariantHolder</code>.
Let's extract this into a base class. Since we are going to make all our
variants derive from it, it must be <code>public</code>, but we probably don't want
clients to derive from it as it is an implementation detail, so we will
provide an <code>internal</code> constructor. This will make this class
instantiable only within the assembly declaring it:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">abstract</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">VariantBase</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">variant</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">Index</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">((</span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">)</span><span class="n">variant</span><span class="p">).</span><span class="n">Item</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="p">();</span>

<span class="w">    </span><span class="k">internal</span><span class="w"> </span><span class="nf">VariantBase</span><span class="p">(</span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">item</span><span class="p">,</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">index</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">        </span><span class="n">Index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">index</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Our <code>Variant&lt;T1, T2&gt;</code> ends up containing only the constructors, casts,
and equality:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">VariantBase</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Calls base constructor</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">item</span><span class="p">,</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">index</span><span class="p">)</span>
<span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="k">base</span><span class="p">(</span><span class="n">item</span><span class="p">,</span><span class="w"> </span><span class="n">index</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// T1 constructor, casts</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="k">this</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T1</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Make1</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>

<span class="w">    </span><span class="c1">// T2 constructor, casts</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="k">this</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T2</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Make2</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>

<span class="w">    </span><span class="c1">// Equality</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="nf">Equals</span><span class="p">(</span><span class="kt">object</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">obj</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">null</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="o">!</span><span class="p">(</span><span class="n">obj</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">))</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">false</span><span class="p">;</span>

<span class="w">        </span><span class="kt">var</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">)</span><span class="n">obj</span><span class="p">;</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">Index</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">Index</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">Get</span><span class="p">().</span><span class="n">Equals</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">Get</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">GetHashCode</span><span class="p">()</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Get</span><span class="p">().</span><span class="n">GetHashCode</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>We can even hoist <code>Equals</code> to our base class, since we can replace the
<code>is</code> check <code>!(obj is Variant&lt;T1, T2&gt;)</code> with
<code>GetType() != obj.GetType()</code>:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">abstract</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">VariantBase</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">readonly</span><span class="w"> </span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">variant</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">Index</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="k">private</span><span class="w"> </span><span class="k">set</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Is</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">((</span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">)</span><span class="n">variant</span><span class="p">).</span><span class="n">Item</span><span class="p">;</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">object</span><span class="w"> </span><span class="nf">Get</span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">variant</span><span class="p">.</span><span class="n">Get</span><span class="p">();</span>

<span class="w">    </span><span class="k">internal</span><span class="w"> </span><span class="nf">VariantBase</span><span class="p">(</span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">item</span><span class="p">,</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">index</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">variant</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">        </span><span class="n">Index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">index</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="nf">Equals</span><span class="p">(</span><span class="kt">object</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">obj</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">null</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">GetType</span><span class="p">()</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">obj</span><span class="p">.</span><span class="n">GetType</span><span class="p">())</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="k">false</span><span class="p">;</span>

<span class="w">        </span><span class="kt">var</span><span class="w"> </span><span class="n">other</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">VariantBase</span><span class="p">)</span><span class="n">obj</span><span class="p">;</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">Index</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">other</span><span class="p">.</span><span class="n">Index</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">Get</span><span class="p">().</span><span class="n">Equals</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">Get</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">GetHashCode</span><span class="p">()</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">Get</span><span class="p">().</span><span class="n">GetHashCode</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>Now our <code>Variant&lt;T1, T2&gt;</code> contains only constructors and casts:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">sealed</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">VariantBase</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Calls base constructor</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">IVariantHolder</span><span class="w"> </span><span class="n">item</span><span class="p">,</span><span class="w"> </span><span class="kt">byte</span><span class="w"> </span><span class="n">index</span><span class="p">)</span>
<span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="k">base</span><span class="p">(</span><span class="n">item</span><span class="p">,</span><span class="w"> </span><span class="n">index</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// T1 constructor, casts</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="k">this</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T1</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Make1</span><span class="p">(</span><span class="n">T1</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>

<span class="w">    </span><span class="c1">// T2 constructor, casts</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Variant</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="p">:</span><span class="w"> </span><span class="k">this</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">implicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">explicit</span><span class="w"> </span><span class="k">operator</span><span class="w"> </span><span class="nf">T2</span><span class="p">(</span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">item</span><span class="p">.</span><span class="n">Get</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Make2</span><span class="p">(</span><span class="n">T2</span><span class="w"> </span><span class="n">item</span><span class="p">)</span>
<span class="w">        </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Variant</span><span class="o">&lt;</span><span class="n">T1</span><span class="p">,</span><span class="w"> </span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">VariantHolder</span><span class="o">&lt;</span><span class="n">T2</span><span class="o">&gt;</span><span class="p">(</span><span class="n">item</span><span class="p">),</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>While C# doesn't provide a way to implement variable number of generic
arguments, constructors and casts for all types are identical, so we can
use a <a href="https://docs.microsoft.com/en-us/visualstudio/modeling/design-time-code-generation-by-using-t4-text-templates">T4 text
template</a>
to generate all this code. Our template would iterate for each type and
emit the C# code for these:</p>
<div class="highlight"><pre><span/>&lt;#
for (int types = 1; types &lt;= 8; types++)
{
    // Comma-delimited string of types (eg. "T1, T2, T3")
    var args = String.Join(", ",
        Enumerable.Range(1, types).Select(i =&gt; "T" + i));

    // Type we are generating code for (eg. "Variant&lt;T1, T2, T3&gt;")
    var type = $"Variant&lt;{args}&gt;";
##&gt;

    public sealed class &lt;#= type #&gt; : VariantBase
    {
        private Variant(IVariantHolder item, byte index)
            : base(item, index)
        {}

&lt;#
    // For each type argument T1, T2, T3 etc.
    for (int i = 1; i &lt;= types; i++)
    {
##&gt;
        public Variant(T&lt;#= i #&gt; item)
            : base(new VariantHolder&lt;T&lt;#= i #&gt;&gt;(item), &lt;#= i - 1 #&gt;)
        {}

        public static implicit operator &lt;#= type #&gt;(T&lt;#= i #&gt; item)
            =&gt; new &lt;#= type #&gt;(item);

        public static explicit operator T&lt;#= i #&gt;(&lt;#= type #&gt; variant)
            =&gt; variant.Get&lt;T&lt;#= i #&gt;&gt;();

        public static &lt;#= type #&gt; Make&lt;#= i #&gt;(T&lt;#= i #&gt; item)
            =&gt; new &lt;#= type #&gt;(new VariantHolder&lt;T&lt;#= i #&gt;&gt;(item), &lt;#= i - 1 #&gt;);
&lt;#
    }
##&gt;
    }

&lt;#
}
##&gt;
</pre></div>

<p>I will not cover T4 templates in this blog post, just highlight that the
template above does generate all the <code>Variant&lt;&gt;</code> variations with the
appropriate constructors and cats.</p>

<p>I am currently working on a type library which includes this variant and
some other useful types: <a href="https://github.com/vladris/Maki">https://github.com/vladris/Maki</a>.</p>

<h2>Summary</h2>

<p>In this post we implemented a generic variant type in C#, going over:</p>

<ul>
<li>Variant types and how they are useful.</li>
<li>Requirements for a variant type.</li>
<li>Implementation:

<ul>
<li>API.</li>
<li>Type erasure.</li>
<li>Disambiguating between similar generic arguments.</li>
<li>Overrides for <code>Equals</code> and <code>GetHashCode</code>.</li>
<li>Implementations for various numbers of generic arguments.</li>
</ul></li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>See <a href="https://en.wikipedia.org/wiki/Tagged_union"><q>tagged union</q> on
Wikipedia</a> <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Mon, 16 Jul 2018 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/06/23/ioc-containers.html</link>
      <guid>https://vladris.com/blog/2018/06/23/ioc-containers.html</guid>
      <title><![CDATA[IoC Containers]]></title>
      <description><![CDATA[<h1>IoC Containers</h1>

<p>In this post I will go over the basics of IoC containers and walk
through a very simple C# implementation.</p>

<h2>Motivation</h2>

<p>An inversion of control container is a component that encapsulates
dependency injection and lifetime management of other components<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>.
Assume we have some well componentized code where classes work against
interfaces:</p>
<div class="highlight"><pre><span/><span class="k">interface</span><span class="w"> </span><span class="n">IFoo</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">void</span><span class="w"> </span><span class="nf">DoFoo</span><span class="p">();</span>
<span class="p">}</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Foo</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">IFoo</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">DoFoo</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Bar</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Coded against IFoo interface, so decoupled from</span>
<span class="w">    </span><span class="c1">// concrete Foo implementation</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="nf">Bar</span><span class="p">(</span><span class="n">IFoo</span><span class="w"> </span><span class="n">foo</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">foo</span><span class="p">.</span><span class="n">DoFoo</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>In order to create an instance of <code>Bar</code>, we need to pass it some <code>IFoo</code>
object. We could do it by <code>new</code>-ing up a <code>Foo</code> object at the call site
of <code>Bar</code>'s constructor:</p>
<div class="highlight"><pre><span/><span class="kt">var</span><span class="w"> </span><span class="n">bar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Bar</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Foo</span><span class="p">());</span>
</pre></div>

<p>This doesn't scale very well though. Most classes require more than one
dependency, so we can't realistically litter the code with:</p>
<div class="highlight"><pre><span/><span class="kt">var</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">A</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">B</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">C</span><span class="p">(),</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">D</span><span class="p">()),</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">E</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">D</span><span class="p">()));</span>
</pre></div>

<p>Factory functions address part of the problem. We can have, for example:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="n">IA</span><span class="w"> </span><span class="nf">MakeIA</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nf">A</span><span class="p">(</span><span class="n">MakeIB</span><span class="p">(),</span><span class="w"> </span><span class="n">MakeIE</span><span class="p">());</span>
<span class="p">}</span>
</pre></div>

<p>Another advantage of using factory functions instead of directly calling
constructors is that a factory can encapsulate lifetime of objects.
Changing from a new instance on every call to a singleton can be
encapsulated in the factory so callers of <code>MakeIA</code> don't need to
change.</p>

<p>We would then call <code>MakeIA</code> whenever we needed an <code>IA</code> instance. But
where do these factories belong? They do not belong with the concrete
types they are implementing, because having a static <code>MakeIA</code> on class
<code>A</code> would still require callers to reference <code>A</code> (as in <code>A.MakeIA()</code>).
Since these factories become the only places in the system where
knowledge of which type resolves to which interface, it makes sense to
keep them together:</p>
<div class="highlight"><pre><span/><span class="k">static</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Factories</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">IA</span><span class="w"> </span><span class="nf">MakeIA</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nf">A</span><span class="p">(</span><span class="n">MakeIB</span><span class="p">(),</span><span class="w"> </span><span class="n">MakeIE</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">IB</span><span class="w"> </span><span class="nf">MakeIB</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nf">B</span><span class="p">(</span><span class="n">MakeIC</span><span class="p">(),</span><span class="w"> </span><span class="n">MakeID</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">IC</span><span class="w"> </span><span class="nf">MakeIC</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nf">C</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">ID</span><span class="w"> </span><span class="nf">MakeID</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nf">D</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">IE</span><span class="w"> </span><span class="nf">MakeIE</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="nf">E</span><span class="p">(</span><span class="n">MakeID</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// ...</span>
<span class="p">}</span>
</pre></div>

<p>This works pretty well: changing which concrete type binds to an
interface becomes a changed scoped to one of the factories. But
maintaining this by hand can become tedious. The good news is it can be
automated, which is what an IoC container does.</p>

<h2>A Basic IoC Container</h2>

<p>A very basic container would be able to bind a concrete implementation
against an interface and return an instance of the concrete
implementation when asked for an interface:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Container</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="n">Register</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="cm">/* ... */</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// ...</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// ...</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>The simplest possible thing to pass to <code>Register</code> is a factory function,
in which case our container would have to maintain a mapping from type
to factory:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Container</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Dictionary</span><span class="o">&lt;</span><span class="n">Type</span><span class="p">,</span><span class="w"> </span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">_registeredTypes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Dictionary</span><span class="o">&lt;</span><span class="n">Type</span><span class="p">,</span><span class="w"> </span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="n">Register</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">Func</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">factory</span><span class="p">)</span><span class="w"> </span><span class="k">where</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="k">class</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">factory</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">T</span><span class="p">)</span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This is how it can be used:</p>
<div class="highlight"><pre><span/><span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">IA</span><span class="o">&gt;</span><span class="p">(()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">A</span><span class="p">(</span><span class="n">Container</span><span class="p">.</span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">IB</span><span class="o">&gt;</span><span class="p">(),</span><span class="w"> </span><span class="n">Container</span><span class="p">.</span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">IE</span><span class="o">&gt;</span><span class="p">()));</span>
<span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">IB</span><span class="o">&gt;</span><span class="p">(()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">B</span><span class="p">(</span><span class="n">Container</span><span class="p">.</span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">IC</span><span class="o">&gt;</span><span class="p">(),</span><span class="w"> </span><span class="n">Container</span><span class="p">.</span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">ID</span><span class="o">&gt;</span><span class="p">()));</span>
<span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">IC</span><span class="o">&gt;</span><span class="p">(()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">C</span><span class="p">());</span>
<span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">ID</span><span class="o">&gt;</span><span class="p">(()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">D</span><span class="p">());</span>
<span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">IE</span><span class="o">&gt;</span><span class="p">(()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">E</span><span class="p">(</span><span class="n">Container</span><span class="p">.</span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">ID</span><span class="o">&gt;</span><span class="p">()));</span>

<span class="c1">// ...</span>

<span class="kt">var</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Container</span><span class="p">.</span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">IA</span><span class="o">&gt;</span><span class="p">();</span>
</pre></div>

<p>This is fine, but still requires a lot of hand-maintenance. One of the
main features of a container is the ability to use reflection and
resolve some of these dependencies automatically. Given a type, we can
find its first public constructor by calling <code>GetConstructor</code> on it:</p>
<div class="highlight"><pre><span/><span class="k">foreach</span><span class="w"> </span><span class="p">(</span><span class="kt">var</span><span class="w"> </span><span class="n">param</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="k">typeof</span><span class="p">(</span><span class="n">A</span><span class="p">).</span><span class="n">GetConstructors</span><span class="p">().</span><span class="n">First</span><span class="p">().</span><span class="n">GetParameters</span><span class="p">())</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Console</span><span class="p">.</span><span class="n">WriteLine</span><span class="p">(</span><span class="n">param</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>So given a type, we should be able to generate a factory function for
it. A simple way of doing it is by calling <code>Invoke</code> on the retrieved
constructor and attempting to retrieve all its arguments from the
container:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="n">Register</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">Type</span><span class="w"> </span><span class="n">type</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">var</span><span class="w"> </span><span class="n">constructor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">type</span><span class="p">.</span><span class="n">GetConstructors</span><span class="p">().</span><span class="n">First</span><span class="p">();</span>

<span class="w">    </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">constructor</span><span class="p">.</span><span class="n">Invoke</span><span class="p">(</span><span class="n">constructor</span><span class="p">.</span><span class="n">GetParameters</span><span class="p">().</span><span class="n">Select</span><span class="p">(</span>
<span class="w">            </span><span class="n">param</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="n">param</span><span class="p">.</span><span class="n">ParameterType</span><span class="p">]()</span>
<span class="w">        </span><span class="p">).</span><span class="n">ToArray</span><span class="p">());</span>
<span class="w">    </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>Now registering the interfaces becomes a lot easier:</p>
<div class="highlight"><pre><span/><span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">IA</span><span class="o">&gt;</span><span class="p">(</span><span class="k">typeof</span><span class="p">(</span><span class="n">A</span><span class="p">));</span>
<span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">IB</span><span class="o">&gt;</span><span class="p">(</span><span class="k">typeof</span><span class="p">(</span><span class="n">B</span><span class="p">));</span>
<span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">IC</span><span class="o">&gt;</span><span class="p">(</span><span class="k">typeof</span><span class="p">(</span><span class="n">C</span><span class="p">));</span>
<span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">ID</span><span class="o">&gt;</span><span class="p">(</span><span class="k">typeof</span><span class="p">(</span><span class="n">D</span><span class="p">));</span>
<span class="n">Container</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">IE</span><span class="o">&gt;</span><span class="p">(</span><span class="k">typeof</span><span class="p">(</span><span class="n">E</span><span class="p">));</span>

<span class="c1">// ...</span>

<span class="kt">var</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Container</span><span class="p">.</span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">IA</span><span class="o">&gt;</span><span class="p">();</span>
</pre></div>

<p>It's usually a good idea to support registration by both type and
factory function, for cases where the construction is more involved or
the types of the constructor arguments, for various reasons, are not
registered with the container.</p>

<h3>Efficient Construction</h3>

<p>Calling <code>Invoke</code> on a <code>ConstructorInfo</code> is notoriously slow<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>. There
are several strategies to make this invocation faster. One of them is by
using <code>System.Linq.Expressions</code>, which are a set of types that help
declare and compile lambdas at runtime:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="n">Register</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">Type</span><span class="w"> </span><span class="n">type</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">var</span><span class="w"> </span><span class="n">constructor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">type</span><span class="p">.</span><span class="n">GetConstructors</span><span class="p">().</span><span class="n">First</span><span class="p">();</span>

<span class="w">    </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="p">)</span><span class="n">Expression</span><span class="p">.</span><span class="n">Lambda</span><span class="p">(</span>
<span class="w">        </span><span class="n">Expression</span><span class="p">.</span><span class="n">New</span><span class="p">(</span><span class="n">constructor</span><span class="p">,</span><span class="w"> </span><span class="n">constructor</span><span class="p">.</span><span class="n">GetParameters</span><span class="p">().</span><span class="n">Select</span><span class="p">(</span>
<span class="w">            </span><span class="n">param</span><span class="w"> </span><span class="o">=&gt;</span>
<span class="w">            </span><span class="p">{</span>
<span class="w">                </span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">resolve</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="n">param</span><span class="p">.</span><span class="n">ParameterType</span><span class="p">]();</span>
<span class="w">                </span><span class="k">return</span><span class="w"> </span><span class="n">Expression</span><span class="p">.</span><span class="n">Convert</span><span class="p">(</span>
<span class="w">                    </span><span class="n">Expression</span><span class="p">.</span><span class="n">Call</span><span class="p">(</span><span class="n">Expression</span><span class="p">.</span><span class="n">Constant</span><span class="p">(</span><span class="n">resolve</span><span class="p">.</span><span class="n">Target</span><span class="p">),</span><span class="w"> </span><span class="n">resolve</span><span class="p">.</span><span class="n">Method</span><span class="p">),</span>
<span class="w">                    </span><span class="n">param</span><span class="p">.</span><span class="n">ParameterType</span><span class="p">);</span>
<span class="w">            </span><span class="p">}</span>
<span class="w">        </span><span class="p">))).</span><span class="n">Compile</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>The above implementation compiles a lambda which is equivalent to the
<code>Invoke</code> logic. There are several other techniques to dynamically
generate functions, including <code>Reflection.Emit</code> and
<code>System.Runtime.CompilerServices</code>. Another decision point is whether
resolution is done lazily or not. The above implementation is lazy,
resolving each constructor parameter does not require an entry for it in
the container when this particular lambda is compiled. The relevant line
is:</p>
<div class="highlight"><pre><span/><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">resolve</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="n">param</span><span class="p">.</span><span class="n">ParameterType</span><span class="p">]();</span>
</pre></div>

<p>If we were to replace this with:</p>
<div class="highlight"><pre><span/><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">resolve</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="n">param</span><span class="p">.</span><span class="n">ParameterType</span><span class="p">];</span>
</pre></div>

<p>it would fail to compile the lambda when registering <code>A</code> unless all
other dependencies are already in the container. This approach is
flexible, in that type bindings can be resolved at runtime, but can
incur a bit more overhead. An alternative would be to register all types
with the container first, then generate the factories in a separate
step. In that case, for each type, we could map out exactly what calls
need to be made to set it up based on information already available to
the container. Such an implementation gets more complex, so I won't go
into the details, but worth noting that it is possible.</p>

<h2>Lifetimes</h2>

<p>Containers also encapsulate lifetime management. The most basic
non-instance lifetime is singleton, which means a unique instance during
the lifetime of the app. Let's extend our container to also support
resolving singletons. First we need a way to wrap a factory into a
function that only calls it once, then caches the result:</p>
<div class="highlight"><pre><span/><span class="k">private</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">SingletonDecorator</span><span class="p">(</span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">factory</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">var</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Lazy</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="p">(</span><span class="n">factory</span><span class="p">);</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">instance</span><span class="p">.</span><span class="n">Value</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This relies on <code>Lazy</code> to ensure uniqueness. Now we can enable singleton
registrations for factories and types:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="n">MarkSingleton</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SingletonDecorator</span><span class="p">(</span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]);</span>
<span class="p">}</span>
</pre></div>

<p>This effectively decorated the registered factory with the singleton
logic. There are various other lifetimes an object could require, for
example: threaded (where instances are cached per thread, so the same
instance is always returned on the same thread but not across threads),
scoped (where there is an API to mark beginning and end of a scope
within which the same instance is always returned, but another one gets
created in another scope) etc.</p>

<h2>A Note on Loading</h2>

<p>One interesting observation made while profiling a .NET application is
that a container usually forces the loading of all referenced assembly.
The .NET runtime defers assembly loading until a method is called which
references a type in a not-yet-loaded assembly. This forces assembly
loading as the runtime needs the metadata of the type. When using an IoC
container, all types are usually registered as soon as the application
boots, in which case all assemblies get pulled in during registration
time (as opposed to on-demand at a later time).</p>

<h2>Resources</h2>

<p>The complete source code for the container in this blog post is:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Container</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Dictionary</span><span class="o">&lt;</span><span class="n">Type</span><span class="p">,</span><span class="w"> </span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">_registeredTypes</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Dictionary</span><span class="o">&lt;</span><span class="n">Type</span><span class="p">,</span><span class="w"> </span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="n">Register</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">Func</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">factory</span><span class="p">)</span><span class="w"> </span><span class="k">where</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="k">class</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">factory</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="n">Register</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">Type</span><span class="w"> </span><span class="n">type</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="kt">var</span><span class="w"> </span><span class="n">constructor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">type</span><span class="p">.</span><span class="n">GetConstructors</span><span class="p">().</span><span class="n">First</span><span class="p">();</span>

<span class="w">        </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="p">)</span><span class="n">Expression</span><span class="p">.</span><span class="n">Lambda</span><span class="p">(</span>
<span class="w">            </span><span class="n">Expression</span><span class="p">.</span><span class="n">New</span><span class="p">(</span><span class="n">constructor</span><span class="p">,</span><span class="w"> </span><span class="n">constructor</span><span class="p">.</span><span class="n">GetParameters</span><span class="p">().</span><span class="n">Select</span><span class="p">(</span>
<span class="w">                </span><span class="n">param</span><span class="w"> </span><span class="o">=&gt;</span>
<span class="w">                </span><span class="p">{</span>
<span class="w">                    </span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">resolve</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="n">param</span><span class="p">.</span><span class="n">ParameterType</span><span class="p">]();</span>
<span class="w">                    </span><span class="k">return</span><span class="w"> </span><span class="n">Expression</span><span class="p">.</span><span class="n">Convert</span><span class="p">(</span>
<span class="w">                        </span><span class="n">Expression</span><span class="p">.</span><span class="n">Call</span><span class="p">(</span><span class="n">Expression</span><span class="p">.</span><span class="n">Constant</span><span class="p">(</span><span class="n">resolve</span><span class="p">.</span><span class="n">Target</span><span class="p">),</span><span class="w"> </span><span class="n">resolve</span><span class="p">.</span><span class="n">Method</span><span class="p">),</span>
<span class="w">                        </span><span class="n">param</span><span class="p">.</span><span class="n">ParameterType</span><span class="p">);</span>
<span class="w">                </span><span class="p">}</span>
<span class="w">            </span><span class="p">))).</span><span class="n">Compile</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="n">MarkSingleton</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SingletonDecorator</span><span class="p">(</span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">T</span><span class="w"> </span><span class="n">Resolve</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">(</span><span class="n">T</span><span class="p">)</span><span class="n">_registeredTypes</span><span class="p">[</span><span class="k">typeof</span><span class="p">(</span><span class="n">T</span><span class="p">)]();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">SingletonDecorator</span><span class="p">(</span><span class="n">Func</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="w"> </span><span class="n">factory</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="kt">var</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Lazy</span><span class="o">&lt;</span><span class="kt">object</span><span class="o">&gt;</span><span class="p">(</span><span class="n">factory</span><span class="p">);</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">instance</span><span class="p">.</span><span class="n">Value</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>I also recently open-sourced a minimal container
<a href="https://github.com/microsoft/minioc">here</a>. That implementation
includes support for scoped lifetimes, but otherwise it is still very
minimal. It was used in a couple of small projects where constraints
were around size/dependent assemblies rather than feature richness.</p>

<p>For a popular open source container with many more features, check out
<a href="https://autofac.org/">AutoFac</a>.</p>

<h2>Summary</h2>

<p>In this post we went over a few IoC container basics:</p>

<ul>
<li>Motivation for containers.</li>
<li>A primitive container supporting factory registration.</li>
<li>Using reflection to support type registration.</li>
<li>Approaches to implementing constructor calls: <code>Inove</code>,
<code>Linq.Expressions</code>, others. Lazy resolution vs. generating
constructor calls in a separate step.</li>
<li>Lifetime management and a singleton implementation.</li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>For a much more detailed treatment, see Martin Fowler's
<a href="https://www.martinfowler.com/articles/injection.html">article</a> <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>An interesting benchmark on <a href="https://stackoverflow.com/questions/35805609/performance-of-expression-compile-vs-lambda-direct-vs-virtual-calls">Stack
Overflow</a> <a href="#fnref2" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sat, 23 Jun 2018 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/04/15/kami-2.html</link>
      <guid>https://vladris.com/blog/2018/04/15/kami-2.html</guid>
      <title><![CDATA[Kami 2]]></title>
      <description><![CDATA[<h1>Kami 2</h1>

<p><a href="https://itunes.apple.com/us/app/kami-2/id1133161444">Kami 2</a> is an iOS
game where the player folds colored paper with the goal of making the
whole screen have the same color. Each level has a set of colors and the
player can pick any of them, color a section, then repeat for a limited
number of steps:</p>

<p><img src="https://vladris.com/blog/2018/04/15/kami-animation.gif" alt="image"/></p>

<p>Some levels are fairly tricky. For example I got stuck on this one:</p>

<p><img src="https://vladris.com/blog/2018/04/15/kami-screenshot.png" alt="image"/></p>

<p>While the app can provide hints, a more interesting exercise is to see
if we can solve this with an algorithm. We can look at this as a graph
problem. Each colored section represents a node in the graph and we
consider adjacent areas as connected by edges:</p>

<p><img src="https://vladris.com/blog/2018/04/15/kami-graph.png" alt="image"/></p>

<p>Here is a more abstract representation of the same level:</p>

<p><img src="https://vladris.com/blog/2018/04/15/graph.png" alt="image"/></p>

<p>The only information we care about is the color of each node and what
other nodes it is connected with.</p>

<p>A step in the game consists of choosing a color, picking a node to get
colored with the chosen colore, then merging the colored node with
adjacent nodes of the same (new) color. The game is won if the nodes get
merged down to a single node within the step limit.</p>

<p>A Python representation of the graph would look like this:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Graph</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodes</span><span class="o">=</span><span class="nb">dict</span><span class="p">(),</span> <span class="n">edges</span><span class="o">=</span><span class="p">[]):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">nodes</span> <span class="o">=</span> <span class="n">nodes</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">edges</span> <span class="o">=</span> <span class="n">edges</span>
</pre></div>

<p>We represent nodes as a dictionary where the key is the node id and the
value is the color of the node, and edge as a list of pairs of ids. The
level diagramed above would be represented as:</p>
<div class="highlight"><pre><span/><span class="n">g</span> <span class="o">=</span> <span class="n">Graph</span><span class="p">(</span>
        <span class="n">nodes</span> <span class="o">=</span> <span class="p">{</span>
            <span class="mi">1</span><span class="p">:</span> <span class="s2">"Purple"</span><span class="p">,</span>
            <span class="mi">2</span><span class="p">:</span> <span class="s2">"Yellow"</span><span class="p">,</span>
            <span class="mi">3</span><span class="p">:</span> <span class="s2">"Red"</span><span class="p">,</span>
            <span class="mi">4</span><span class="p">:</span> <span class="s2">"Yellow"</span><span class="p">,</span>
            <span class="mi">5</span><span class="p">:</span> <span class="s2">"White"</span><span class="p">,</span>
            <span class="mi">6</span><span class="p">:</span> <span class="s2">"Purple"</span><span class="p">,</span>
            <span class="mi">7</span><span class="p">:</span> <span class="s2">"Yellow"</span><span class="p">,</span>
            <span class="mi">8</span><span class="p">:</span> <span class="s2">"Purple"</span><span class="p">,</span>
            <span class="mi">9</span><span class="p">:</span> <span class="s2">"Yellow"</span><span class="p">,</span>
            <span class="mi">10</span><span class="p">:</span> <span class="s2">"Red"</span><span class="p">,</span>
            <span class="mi">11</span><span class="p">:</span> <span class="s2">"Purple"</span><span class="p">,</span>
            <span class="mi">12</span><span class="p">:</span> <span class="s2">"White"</span><span class="p">,</span>
            <span class="mi">13</span><span class="p">:</span> <span class="s2">"Purple"</span><span class="p">,</span>
            <span class="mi">14</span><span class="p">:</span> <span class="s2">"Purple"</span><span class="p">,</span>
            <span class="mi">15</span><span class="p">:</span> <span class="s2">"White"</span><span class="p">,</span>
            <span class="mi">16</span><span class="p">:</span> <span class="s2">"Yellow"</span><span class="p">,</span>
            <span class="mi">17</span><span class="p">:</span> <span class="s2">"Red"</span><span class="p">,</span>
            <span class="mi">18</span><span class="p">:</span> <span class="s2">"Purple"</span><span class="p">,</span>
        <span class="p">},</span>
        <span class="n">edges</span> <span class="o">=</span> <span class="p">[</span>
            <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">6</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">7</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">8</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">6</span><span class="p">,</span> <span class="mi">9</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">9</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">7</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="mi">10</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">11</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">9</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">11</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">13</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">13</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">14</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">12</span><span class="p">,</span> <span class="mi">16</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">13</span><span class="p">,</span> <span class="mi">15</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">13</span><span class="p">,</span> <span class="mi">16</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">13</span><span class="p">,</span> <span class="mi">18</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="mi">18</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">17</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">16</span><span class="p">,</span> <span class="mi">18</span><span class="p">),</span>
            <span class="p">(</span><span class="mi">17</span><span class="p">,</span> <span class="mi">18</span><span class="p">),</span>
        <span class="p">])</span>
</pre></div>

<p>We need a function that, for a given node id, enumerates all the
connected nodes. This is a member function of the graph:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">connected</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">edge</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">edges</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="n">node</span><span class="p">:</span>
            <span class="k">yield</span> <span class="n">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
        <span class="k">elif</span> <span class="n">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="n">node</span><span class="p">:</span>
            <span class="k">yield</span> <span class="n">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
</pre></div>

<p>We also need a function that colors a node and merges it with adjacent
nodes of the same color. We can make this function return a new graph
instance with the applied updates. Its signature would be:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">color</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">color</span><span class="p">):</span>
</pre></div>

<p>First it would have to determine the set of nodes that need to be merged
after coloring. That is the node that just got colored and adjacent
nodes which have the same color as its new color. By convention, when we
merge nodes we keep the smallest id:</p>
<div class="highlight"><pre><span/><span class="n">to_merge</span> <span class="o">=</span> <span class="p">[</span><span class="n">node</span><span class="p">]</span>
<span class="n">to_merge</span> <span class="o">+=</span> <span class="p">[</span><span class="n">n</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">connected</span><span class="p">(</span><span class="n">node</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodes</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">==</span> <span class="n">color</span><span class="p">]</span>
<span class="n">new_n</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">to_merge</span><span class="p">)</span>
</pre></div>

<p>The nodes of the new graph would be the same nodes as the old one, minus
any node in <code>to_merge</code>. Nodes in the <code>to_merge</code> list would be
represented by the node <code>new_n</code>:</p>
<div class="highlight"><pre><span/><span class="n">new_nodes</span> <span class="o">=</span> <span class="p">{</span> <span class="n">new_n</span><span class="p">:</span> <span class="n">color</span> <span class="p">}</span>
<span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodes</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">node</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">to_merge</span><span class="p">:</span>
        <span class="n">new_nodes</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodes</span><span class="p">[</span><span class="n">node</span><span class="p">]</span>
</pre></div>

<p>We also need to build the new list of edges. We do this as follows: for
each edge, if both nodes are in <code>to_merge</code>, the edge does not exist in
the new graph so we discard it. If one node is in <code>to_merge</code>, we create
a new edge where the node in <code>to_merge</code> is replaced by <code>new_n</code>. If none
of the nodes is in <code>to_merge</code>, we keeep the edge:</p>
<div class="highlight"><pre><span/><span class="n">new_edges</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">for</span> <span class="n">edge</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">edges</span><span class="p">:</span>
    <span class="k">if</span> <span class="n">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">to_merge</span> <span class="ow">and</span> <span class="n">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="n">to_merge</span><span class="p">:</span>
        <span class="k">continue</span>
    <span class="k">elif</span> <span class="n">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">to_merge</span><span class="p">:</span>
        <span class="n">new_edges</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="nb">sorted</span><span class="p">((</span><span class="n">new_n</span><span class="p">,</span> <span class="n">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]))))</span>
    <span class="k">elif</span> <span class="n">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="n">to_merge</span><span class="p">:</span>
        <span class="n">new_edges</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="nb">sorted</span><span class="p">((</span><span class="n">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">new_n</span><span class="p">))))</span>
    <span class="k">else</span><span class="p">:</span>
        <span class="n">new_edges</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">edge</span><span class="p">)</span>
</pre></div>

<p>We keep the edge tuples sorted by node id to avoid duplication (for
example having both a <code>(1, 3)</code> and a <code>(3, 1)</code>). We return a graph
consiting of <code>new_nodes</code> and <code>new_edges</code>. The full implementation of
<code>color</code> is:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">color</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">,</span> <span class="n">color</span><span class="p">):</span>
    <span class="n">to_merge</span> <span class="o">=</span> <span class="p">[</span><span class="n">node</span><span class="p">]</span>
    <span class="n">to_merge</span> <span class="o">+=</span> <span class="p">[</span><span class="n">n</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">connected</span><span class="p">(</span><span class="n">node</span><span class="p">)</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodes</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">==</span> <span class="n">color</span><span class="p">]</span>
    <span class="n">new_n</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">to_merge</span><span class="p">)</span>

    <span class="n">new_nodes</span> <span class="o">=</span> <span class="p">{</span> <span class="n">new_n</span><span class="p">:</span> <span class="n">color</span> <span class="p">}</span>
    <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodes</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">node</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">to_merge</span><span class="p">:</span>
            <span class="n">new_nodes</span><span class="p">[</span><span class="n">node</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodes</span><span class="p">[</span><span class="n">node</span><span class="p">]</span>

    <span class="n">new_edges</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">edge</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">edges</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">to_merge</span> <span class="ow">and</span> <span class="n">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="n">to_merge</span><span class="p">:</span>
            <span class="k">continue</span>
        <span class="k">elif</span> <span class="n">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="ow">in</span> <span class="n">to_merge</span><span class="p">:</span>
            <span class="n">new_edges</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="nb">sorted</span><span class="p">((</span><span class="n">new_n</span><span class="p">,</span> <span class="n">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]))))</span>
        <span class="k">elif</span> <span class="n">edge</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">in</span> <span class="n">to_merge</span><span class="p">:</span>
            <span class="n">new_edges</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="nb">tuple</span><span class="p">(</span><span class="nb">sorted</span><span class="p">((</span><span class="n">edge</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">new_n</span><span class="p">))))</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">new_edges</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">edge</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">Graph</span><span class="p">(</span><span class="n">new_nodes</span><span class="p">,</span> <span class="n">new_edges</span><span class="p">)</span>
</pre></div>

<p>To solve a level we try coloring all of the nodes then recursively solve
for the new graph. If our graph has one node, we found a solution. If we
run out of steps, our candidate solution is not good so we backtrack:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">solve</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">steps</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">graph</span><span class="o">.</span><span class="n">nodes</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="nb">print</span><span class="p">(</span><span class="n">steps</span><span class="p">)</span>
        <span class="n">exit</span><span class="p">()</span>

    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">graph</span><span class="o">.</span><span class="n">nodes</span><span class="p">:</span>
        <span class="n">colors</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">([</span><span class="n">graph</span><span class="o">.</span><span class="n">nodes</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">graph</span><span class="o">.</span><span class="n">connected</span><span class="p">(</span><span class="n">node</span><span class="p">)]))</span>
        <span class="k">for</span> <span class="n">color</span> <span class="ow">in</span> <span class="n">colors</span><span class="p">:</span>
            <span class="n">g</span> <span class="o">=</span> <span class="n">graph</span><span class="o">.</span><span class="n">color</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">color</span><span class="p">)</span>
            <span class="n">solve</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">steps</span> <span class="o">+</span> <span class="p">[(</span><span class="n">node</span><span class="p">,</span> <span class="n">color</span><span class="p">)],</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>

<p>Here <code>graph</code> is the graph we are trying to solve, <code>steps</code> is the list of
actions in our solution, consisting of pairs of node id and color, and
<code>n</code> is the remaining number of steps.</p>

<p>Note that we don't attempt to color a node with any random color,
rather we want to color it with the color of one of its adjacent nodes.
The reason for this is that such a coloring guarantees <em>some</em> nodes will
get merged so we reduce the total number of nodes with this step. If we
were to color a node with a color none of its adjacent nodes has, there
would be nothing to merge so we would waste a step without reducing the
graph.</p>

<p>This solution works but is rather slow. One optimization we can do is to
more aggressively prune our search space: if at any point our graph has
more colors than the number of remaining steps + 1, we know we are down
the wrong path and need to backtrack. As an example, if we have four
colors on the board: blue, red, yellow, white, but we only have 2 steps
left, no matter how the areas are connected, we can never end up with a
single color in 2 steps as we need to recolor 3 areas.</p>

<p>We can implement this optimization by updating the <code>Graph</code> constructor
to keep track of the number of unique colors and update our <code>solve</code>
function to backtrack if we have more colors than steps + 1:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Graph</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodes</span><span class="o">=</span><span class="nb">dict</span><span class="p">(),</span> <span class="n">edges</span><span class="o">=</span><span class="p">[]):</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">nodes</span> <span class="o">=</span> <span class="n">nodes</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">edges</span> <span class="o">=</span> <span class="n">edges</span>
        <span class="bp">self</span><span class="o">.</span><span class="n">colors</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">nodes</span><span class="o">.</span><span class="n">values</span><span class="p">()))</span>
</pre></div>

<p>The update is the last line, which maintains the count of unique values
in the <code>nodes</code> dictionary. Updated <code>solve</code> looks like this:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">solve</span><span class="p">(</span><span class="n">graph</span><span class="p">,</span> <span class="n">steps</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">graph</span><span class="o">.</span><span class="n">nodes</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="nb">print</span><span class="p">(</span><span class="n">steps</span><span class="p">)</span>
        <span class="n">exit</span><span class="p">()</span>

    <span class="k">if</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="k">if</span> <span class="n">graph</span><span class="o">.</span><span class="n">colors</span> <span class="o">&gt;</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:</span>
        <span class="k">return</span>

    <span class="k">for</span> <span class="n">node</span> <span class="ow">in</span> <span class="n">graph</span><span class="o">.</span><span class="n">nodes</span><span class="p">:</span>
        <span class="n">colors</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="nb">set</span><span class="p">([</span><span class="n">graph</span><span class="o">.</span><span class="n">nodes</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">graph</span><span class="o">.</span><span class="n">connected</span><span class="p">(</span><span class="n">node</span><span class="p">)]))</span>
        <span class="k">for</span> <span class="n">color</span> <span class="ow">in</span> <span class="n">colors</span><span class="p">:</span>
            <span class="n">g</span> <span class="o">=</span> <span class="n">graph</span><span class="o">.</span><span class="n">color</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">color</span><span class="p">)</span>
            <span class="n">solve</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="n">steps</span> <span class="o">+</span> <span class="p">[(</span><span class="n">node</span><span class="p">,</span> <span class="n">color</span><span class="p">)],</span> <span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</pre></div>

<p>We introduced a new <code>if</code> statement that returns if
<code>graph.colors &gt; n + 1</code>.</p>

<p>Running this yields the following solution for the level:</p>
<div class="highlight"><pre><span/><span class="p">[(</span><span class="mi">10</span><span class="p">,</span> <span class="s1">'Purple'</span><span class="p">),</span> <span class="p">(</span><span class="mi">8</span><span class="p">,</span> <span class="s1">'White'</span><span class="p">),</span> <span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="s1">'Yellow'</span><span class="p">),</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="s1">'Purple'</span><span class="p">),</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'Red'</span><span class="p">)]</span>
</pre></div>

<p>So coloring node 10 with purple, then node 8 with white and so on solves
the level.</p>

<p>Another potential optimization which I did not implement could improve
pruning further by relying on the fact that coloring a node and merging
it with adjacent nodes removes at most two edges from a path. So if the
shortest path between two nodes in the graph is longer than twice the
number of remaining steps, we would again not be able to find a solution
from the current state.</p>

<p>The full source code is available <a href="https://gist.github.com/vladris/c283de5d8a3289303c7aca258e9cbdb1">on
GitHub</a>.</p>
]]></description>
      <pubDate>Sun, 15 Apr 2018 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/02/11/fibonacci.html</link>
      <guid>https://vladris.com/blog/2018/02/11/fibonacci.html</guid>
      <title><![CDATA[Fibonacci]]></title>
      <description><![CDATA[<h1>Fibonacci</h1>

<p>This blog post looks at a few algorithms to generate Fibonacci numbers.
For a much better treatment of these algorithms, I recommend <a href="https://www.goodreads.com/book/show/23498372-from-mathematics-to-generic-programming">From
Mathematics to Generic
Programming</a>.
The implementations are provided in poorly written Rust, as I'm just
learning the language.</p>

<p>Learning Rust and going through <a href="https://doc.rust-lang.org/book/second-edition/">The Rust Programming
Language</a>, I got to <a href="https://doc.rust-lang.org/book/second-edition/ch03-05-control-flow.html#summary">the
end of chapter
3</a>,
where there are a few simple exercises. One of them is <em>Generate the nth
Fibonacci number</em>.</p>

<h2>The Fibonacci Sequence</h2>

<p>The Fibonacci sequence is defined as the sequence
\(F_n = F_{n-1} + F_{n-2}\) with the seed values \(F_0 = 0\) and \(F_1 = 1\).</p>

<p>The first few values of the sequence are 0, 1, 1, 2, 3, 5, 8, 13, 21,
34, 55, 89, 144, ....</p>

<h2>A NaÃ¯ve Algorithm</h2>

<p>Directly translating the definition above into an algorithm to compute
the n-th Fibonacci number yields:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">fib</span><span class="p">(</span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">fib</span><span class="p">(</span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>

<p>This algorithm works for very small <code>n</code> values but it is extremely
inefficient as it has exponential time complexity and linear space
complexity (based on stack depth). Since
<code>fib(n - 1) = fib(n - 2) + fib(n - 3)</code>, a call like
<code>fib(n - 1) + fib(n - 2)</code> is equivalent to
<code>(fib(n - 2) + fib(n - 3)) + fib(n - 2)</code>, so the same elements of the
sequence end up being computed over and over again.</p>

<h2>Bottom-Up Approach</h2>

<p>A better way to generate the nth Fibonacci number is to build it
bottom-up, starting from \(F_0\) and \(F_1\):</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">fib2</span><span class="p">(</span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">..</span><span class="n">n</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">b</span><span class="p">;</span>
<span class="w">        </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">b</span><span class="p">;</span>
<span class="w">        </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">c</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">b</span>
<span class="p">}</span>
</pre></div>

<p>Here we start with \(a = F_0, b = F_1\) and with each iteration of the
loop we advance from \(a = F_k, b = F_{k+1}\) to
\(a = F_{k+1}, b = F_{k+2}\) until <code>b</code> becomes \(F_n\).</p>

<p>Compared to the first algorithm, this is highly efficient, as it has
linear complexity and requires constant space. There are faster ways to
compute the nth Fibonacci number though.</p>

<h2>Matrix Form</h2>

<p>The Fibonacci sequence can also be described in matrix form as follows:</p>

<p>\[\begin{aligned}
\begin{bmatrix}
    F_{k+2} \\
    F_{k+1}
\end{bmatrix}=\begin{bmatrix}
    1 &amp; 1 \\
    1 &amp; 0
\end{bmatrix}*\begin{bmatrix}
    F_{k+1} \\
    F_k
\end{bmatrix}
\end{aligned}\]</p>

<p>Note that the next pair of numbers in the sequence, \(F_{k+3}, F_{k+2}\)
can be expressed as:</p>

<p>\[\begin{aligned}
\begin{bmatrix}
    F_{k+3} \\
    F_{k+2}
\end{bmatrix}=\begin{bmatrix}
    1 &amp; 1 \\
    1 &amp; 0
\end{bmatrix}*\begin{bmatrix}
    F_{k+2} \\
    F_{k+1}
\end{bmatrix}=\begin{bmatrix}
    1 &amp; 1 \\
    1 &amp; 0
\end{bmatrix}*\begin{bmatrix}
    1 &amp; 1 \\
    1 &amp; 0
\end{bmatrix}*\begin{bmatrix}
    F_{k+1} \\
    F_k
\end{bmatrix}
\end{aligned}\]</p>

<p>Thus we have the formula:</p>

<p>\[\begin{aligned}
\begin{bmatrix}
    F_n \\
    F_n - 1
\end{bmatrix}=\begin{bmatrix}
    1 &amp; 1 \\
    1 &amp; 0
\end{bmatrix}^{n-1}*\begin{bmatrix}
    F_1 \\
    F_0
\end{bmatrix}
\end{aligned}\]</p>

<p>Since \(F_0 = 0\) and \(F_1 = 1\), \(F_n\) is the element at index \((0, 0)\)
in:</p>

<p>\[\begin{aligned}
\begin{bmatrix}
1 &amp; 1 \\
1 &amp; 0
\end{bmatrix}^{n-1}
\end{aligned}\]</p>

<p>Assuming we have a function for exponentiating 2x2 matrices <code>exp2x2</code>, we
can implement an algorithm to compute the nth Fibonacci number like
this:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">fib3</span><span class="p">(</span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span>
<span class="w">        </span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">],</span>
<span class="w">        </span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">],</span>
<span class="w">    </span><span class="p">];</span>

<span class="w">    </span><span class="n">exp2x2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="p">}</span>
</pre></div>

<p>The complexity of this algorithm is given by the complexity of <code>exp2x2</code>.
A simple implementation of matrix exponentiation given a matrix
multiplication function <code>mul2x2</code> is:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">exp2x2</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span>
<span class="w">        </span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">],</span>
<span class="w">        </span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">],</span>
<span class="w">    </span><span class="p">];</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">0</span><span class="o">..</span><span class="n">n</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mul2x2</span><span class="p">(</span><span class="n">result</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">result</span>
<span class="p">}</span>
</pre></div>

<p>This function computes <code>a^n</code> by starting with the identity matrix and
multiplying it with a n times. The function for multiplying two 2x2
matrices is trivial:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">mul2x2</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">b</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">])</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">[</span>
<span class="w">        </span><span class="p">[</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]],</span>
<span class="w">        </span><span class="p">[</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]],</span>
<span class="w">    </span><span class="p">]</span>
<span class="p">}</span>
</pre></div>

<p>With <code>mul2x2</code> and <code>exp2x2</code>, our <code>fib3</code> algorithm has linear complexity,
which is determined by the number of times we call <code>mul2x2</code> in our
exponentiation function. There is a faster way to do exponentiation
though: observe that \(x^7 = x^4 * x^2 * x\). In general, any number <code>n</code>
and can be decomposed as a series of powers of two. So we can implement
a <code>fast_exp2x2</code> which works as follows:</p>
<div class="highlight"><pre><span/>if n == 1, return a
if n is even, return fast_exp2x2(a * a, n / 2)
if n is odd, return fast_exp2x2(a * a, (n - 1) / 2) * a
</pre></div>

<p>We stop when our exponent is 1 and return <code>a</code>. If <code>n</code> is even, we square
the base and halve the exponent (for example \(x^8 = (x*x)^4\)). If <code>n</code> is
odd, we do the same but multiply by the base (for example
\(x^9 = (x*x)^4 *
x\)). This is a recursive algorithm which halves <code>n</code> at each step, so we
have logarithmic time and space complexity.</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">fast_exp2x2</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fast_exp2x2</span><span class="p">(</span><span class="n">mul2x2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">),</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mul2x2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">result</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">result</span>
<span class="p">}</span>
</pre></div>

<p>This is a very efficient way to compute the nth Fibonacci number. But
where does this fast exponentiation algorithm come from?</p>

<h2>Ancient Egyptian Multiplication</h2>

<p>The ancient Egyptian multiplication algorithm comes from the <a href="Rhind%20Mathematical%20Papyrus">Rhind
Papyrus</a> from around 1500 BC. The idea
is very similar to our fast exponentiation algorithm: we can implement a
fast multiplication algorithm by relying on addition and doubling (eg.
\(x * 7 = x * 4 + x * 2 + x\)). The steps or our <code>egyptian_mul</code> algorithm
are:</p>
<div class="highlight"><pre><span/>if n == 1, return a
if n is even, return egyptian_mul(a + a, n / 2)
if n is odd, return egyptian_mul(a + a, (n - 1) / 2) + a
</pre></div>

<p>An implementation in Rust is:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">egyptian_mul</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">egyptian_mul</span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">result</span>
<span class="p">}</span>
</pre></div>

<p>This multiplication algorithm relies only on addition, and multiplies
<code>a</code> by <code>n</code> in \(log(n)\) steps.</p>

<p><code>egyptian_mul</code> and <code>fast_exp2x2</code> algorithms have the same structure
since they are fundamentally the same: they provide an efficient way to
implement an operation defined as applying another operation n times.
Multiplication is, by definition, repeated addition. Similarly,
exponentiation is, by definition, repeated multiplication. We can
generalize these to an algorithm that given an initial value <code>a</code> of any
type <code>T</code>, an operation <code>op(T, T) -&gt; T</code>, and <code>n</code>, the number of times to
apply <code>op</code>, provides an efficient computation using doubling and
halving:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">op_n_times</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="o">&gt;</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="n">op</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="nc">Op</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="nc">T</span>
<span class="w">    </span><span class="k">where</span><span class="w"> </span><span class="n">T</span><span class="p">:</span><span class="w"> </span><span class="nb">Copy</span><span class="p">,</span>
<span class="w">          </span><span class="n">Op</span><span class="p">:</span><span class="w"> </span><span class="nb">Fn</span><span class="p">(</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="nc">T</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op_n_times</span><span class="p">::</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">a</span><span class="p">),</span><span class="w"> </span><span class="o">&amp;</span><span class="n">op</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">result</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">result</span>
<span class="p">}</span>
</pre></div>

<p>We can express Egyptian multiplication (<code>egyptian_mul</code>) as addition
applied <code>n</code> times:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">egyptian_mul</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="kt">i32</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">op_n_times</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">std</span><span class="p">::</span><span class="n">ops</span><span class="p">::</span><span class="n">Add</span><span class="p">::</span><span class="n">add</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>

<p>Similarly, we can express fast matrix exponentiation (<code>fast_exp2x2</code>) as
matrix multiplication applied <code>n</code> times:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">fast_exp2x2</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="p">[[</span><span class="kt">i32</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">op_n_times</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">mul2x2</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="p">}</span>
</pre></div>

<h2>Industrial Strength Fibonacci</h2>

<p>I wanted to benchmark the two interesting implementations: <code>fib2</code> and
<code>fib4</code>. The first exponential complexity implementation is highly
inefficient and even for small values of <code>N</code> (eg. <code>N = 50</code>) it takes a
long time to complete. <code>fib3</code> has linear complexity like <code>fib2</code>, but
while <code>fib2</code> just performs additions and assignments on each iteration,
<code>fib3</code> performs matrix multiplication, which is more expensive. So
<code>fib2</code> and <code>fib4</code> are more interesting to look at.</p>

<p>Turns out that the Fibonacci sequence grows quite fast, the 100th
Fibonacci number is <code>354224848179261915075</code>, which does not fit in an
<code>i32</code>. So let's update the implementations to use <code>num::BigUint</code>, an
arbitrary precision number. First is <code>fib2</code>:</p>
<div class="highlight"><pre><span/><span class="k">extern</span><span class="w"> </span><span class="k">crate</span><span class="w"> </span><span class="n">num</span><span class="p">;</span>

<span class="k">use</span><span class="w"> </span><span class="n">num</span><span class="p">::</span><span class="n">bigint</span><span class="p">::{</span><span class="n">BigUint</span><span class="p">,</span><span class="w"> </span><span class="n">ToBigUint</span><span class="p">};</span>

<span class="k">fn</span><span class="w"> </span><span class="nf">fib2</span><span class="p">(</span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="nc">BigUint</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">0.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">0.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mf">1.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="n">_</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="mi">1</span><span class="o">..</span><span class="n">n</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="kd">let</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">;</span>
<span class="w">        </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">b</span><span class="p">;</span>
<span class="w">        </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">c</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">b</span>
<span class="p">}</span>
</pre></div>

<p>For <code>fib4</code>, we need to update <code>mul2x2</code> to work with <code>BigUint</code> array
references, so we don't copy <code>BigUint</code> arrays:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">mul2x2</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="p">[[</span><span class="n">BigUint</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">b</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="p">[[</span><span class="n">BigUint</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">])</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="p">[[</span><span class="n">BigUint</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">[</span>
<span class="w">        </span><span class="p">[</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]],</span>
<span class="w">        </span><span class="p">[</span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">],</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="o">&amp;</span><span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]],</span>
<span class="w">    </span><span class="p">]</span>
<span class="p">}</span>
</pre></div>

<p>We also need to update our <code>op_n_times</code> so the operation now takes <code>&amp;T</code>
instead of <code>T</code>. Note this version still works with <code>i32</code> arrays and
numbers, but now the operation is expected to take two references
instead of two values. On the other hand we no longer require that <code>T</code>
has the <code>Copy</code> trait:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">op_n_times</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="o">&gt;</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="n">op</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="nc">Op</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="nc">T</span>
<span class="w">    </span><span class="k">where</span><span class="w"> </span><span class="n">Op</span><span class="p">:</span><span class="w"> </span><span class="nb">Fn</span><span class="p">(</span><span class="o">&amp;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">T</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="nc">T</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op_n_times</span><span class="p">::</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="n">Op</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op</span><span class="p">(</span><span class="o">&amp;</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">a</span><span class="p">),</span><span class="w"> </span><span class="o">&amp;</span><span class="n">op</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="o">&amp;</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">result</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">result</span>
<span class="p">}</span>
</pre></div>

<p>Then we can update our <code>fib4</code> implementation to use <code>BigUint</code>:</p>
<div class="highlight"><pre><span/><span class="k">fn</span><span class="w"> </span><span class="nf">fast_exp2x2</span><span class="p">(</span><span class="n">a</span><span class="p">:</span><span class="w"> </span><span class="p">[[</span><span class="n">BigUint</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">],</span><span class="w"> </span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="p">[[</span><span class="n">BigUint</span><span class="p">;</span><span class="w"> </span><span class="mi">2</span><span class="p">];</span><span class="w"> </span><span class="mi">2</span><span class="p">]</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">op_n_times</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="o">&amp;</span><span class="n">mul2x2</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="p">}</span>

<span class="k">fn</span><span class="w"> </span><span class="nf">fib4</span><span class="p">(</span><span class="n">n</span><span class="p">:</span><span class="w"> </span><span class="kt">i32</span><span class="p">)</span><span class="w"> </span><span class="p">-&gt;</span><span class="w"> </span><span class="nc">BigUint</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">0.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="mf">1.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">();</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[</span>
<span class="w">        </span><span class="p">[</span><span class="mf">1.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">(),</span><span class="w"> </span><span class="mf">1.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()],</span>
<span class="w">        </span><span class="p">[</span><span class="mf">1.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">(),</span><span class="w"> </span><span class="mf">0.</span><span class="n">to_biguint</span><span class="p">().</span><span class="n">unwrap</span><span class="p">()],</span>
<span class="w">    </span><span class="p">];</span>

<span class="w">    </span><span class="n">fast_exp2x2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">].</span><span class="n">clone</span><span class="p">()</span>
<span class="p">}</span>
</pre></div>

<p>These two implementations work with arbitrarily large numbers, for
example <code>fib4(10_000)</code> is:</p>

<blockquote style="word-wrap:break-word">
33644764876431783266621612005107543310302148460680063906564769974680081442166662368155595513633734025582065332680836159373734790483865268263040892463056431887354544369559827491606602099884183933864652731300088830269235673613135117579297437854413752130520504347701602264758318906527890855154366159582987279682987510631200575428783453215515103870818298969791613127856265033195487140214287532698187962046936097879900350962302291026368131493195275630227837628441540360584402572114334961180023091208287046088923962328835461505776583271252546093591128203925285393434620904245248929403901706233888991085841065183173360437470737908552631764325733993712871937587746897479926305837065742830161637408969178426378624212835258112820516370298089332099905707920064367426202389783111470054074998459250360633560933883831923386783056136435351892133279732908133732642652633989763922723407882928177953580570993691049175470808931841056146322338217465637321248226383092103297701648054726243842374862411453093812206564914032751086643394517512161526545361333111314042436854805106765843493523836959653428071768775328348234345557366719731392746273629108210679280784718035329131176778924659089938635459327894523777674406192240337638674004021330343297496902028328145933418826817683893072003634795623117103101291953169794607632737589253530772552375943788434504067715555779056450443016640119462580972216729758615026968443146952034614932291105970676243268515992834709891284706740862008587135016260312071903172086094081298321581077282076353186624611278245537208532365305775956430072517744315051539600905168603220349163222640885248852433158051534849622434848299380905070483482449327453732624567755879089187190803662058009594743150052402532709746995318770724376825907419939632265984147498193609285223945039707165443156421328157688908058783183404917434556270520223564846495196112460268313970975069382648706613264507665074611512677522748621598642530711298441182622661057163515069260029861704945425047491378115154139941550671256271197133252763631939606902895650288268608362241082050562430701794976171121233066073310059947366875
</blockquote>

<p>We can benchmark these implementations using Rust's built-in
benchmarking:</p>
<div class="highlight"><pre><span/><span class="p">#</span><span class="cp">#[bench]</span>
<span class="k">fn</span><span class="w"> </span><span class="nf">fib4_bench</span><span class="p">(</span><span class="n">b</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Bencher</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">fib4</span><span class="p">(</span><span class="n">N</span><span class="p">));</span>
<span class="p">}</span>

<span class="p">#</span><span class="cp">#[bench]</span>
<span class="k">fn</span><span class="w"> </span><span class="nf">fib2_bench</span><span class="p">(</span><span class="n">b</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="nc">mut</span><span class="w"> </span><span class="n">Bencher</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">b</span><span class="p">.</span><span class="n">iter</span><span class="p">(</span><span class="o">||</span><span class="w"> </span><span class="n">fib2</span><span class="p">(</span><span class="n">N</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>On my Surface Book, for <code>N = 100</code>, we have:</p>
<div class="highlight"><pre><span/>test tests::fib2_bench ... bench:       7,805 ns/iter (+/- 3,042)
test tests::fib4_bench ... bench:       6,140 ns/iter (+/- 356)
</pre></div>

<p>For <code>N = 1_000</code>:</p>
<div class="highlight"><pre><span/>test tests::fib2_bench ... bench:      89,131 ns/iter (+/- 28,346)
test tests::fib4_bench ... bench:      16,307 ns/iter (+/- 2,087)
</pre></div>

<p>For <code>N = 10_000</code>:</p>
<div class="highlight"><pre><span/>test tests::fib2_bench ... bench:   2,121,140 ns/iter (+/- 132,448)
test tests::fib4_bench ... bench:     184,625 ns/iter (+/- 12,184)
</pre></div>

<p>For <code>N = 100_000</code>:</p>
<div class="highlight"><pre><span/>test tests::fib2_bench ... bench: 128,769,418 ns/iter (+/- 5,198,789)
test tests::fib4_bench ... bench:   7,176,026 ns/iter (+/- 364,400)
</pre></div>

<p>While <code>fib2</code> and <code>fib4</code> start with about the same performance at
<code>N = 100</code>, for <code>N = 100_000</code>, <code>fib4</code> is significantly faster. The
benchmark results don't seem to reflect the algorithmic complexity of
<code>fib2</code> (linear) and <code>fib4</code> (logarithmic), I suspect because of the
introduction of <code>BigUint</code> and operations on large numbers. Still, the
algorithm relying on fast exponentiation performs many times faster on
large Ns.</p>

<h2>Summary</h2>

<p>This blog post covered:</p>

<ul>
<li>Algorithms to generate Fibonacci numbers: naÃ¯ve recursive
(exponential), bottom-up (linear), matrix exponentiation (linear or
logarithmic, depending on the matrix exponentiation algorithm).</li>
<li>Ancient Egyptian multiplication and fast matrix exponentiation are
the same algorithm applied to different operations.</li>
<li>A generic algorithm of efficiently applying an operation n times.</li>
<li>Algorithms to generate Fibonacci numbers implemented with <code>BigUint</code>
for arbitrary precision numbers.</li>
<li>Benchmarking the <code>fib2</code> and <code>fib4</code> algorithms shows <code>fib4</code> to be
much better as <code>N</code> increases.</li>
</ul>

<p>My humble conclusion is that generating Fibonacci numbers is more than
an introductory exercise.</p>
]]></description>
      <pubDate>Sun, 11 Feb 2018 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2018/01/27/notes-on-oop.html</link>
      <guid>https://vladris.com/blog/2018/01/27/notes-on-oop.html</guid>
      <title><![CDATA[Notes on OOP]]></title>
      <description><![CDATA[<h1>Notes on OOP</h1>

<p>I am not a huge fan of <q>pure</q> OOP. In this post I will cover a few
non-pure OOP concepts: subtyping wihtout inheritance, mixins, free
functions, and types without invariants. I will make a case for why
multi-paradigm is needed and how using a wider variety of concepts
enables us to build simpler systems.</p>

<h2>Duck typing</h2>

<blockquote>
<p>If it walks like a duck and it quacks like a duck, then it must be a
duck.</p>
</blockquote>

<p>Let's say we have a <code>Duck</code> class. A <code>Duck</code> quacks and waddles:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Duck</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Quack</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Waddle</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>We have a function that uses a duck:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">Duck</span><span class="o">&amp;</span><span class="w"> </span><span class="n">duck</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">duck</span><span class="p">.</span><span class="n">Quack</span><span class="p">();</span>
<span class="w">    </span><span class="n">duck</span><span class="p">.</span><span class="n">Waddle</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>The object-oriented way to implement subtyping is to inherit from the
base class:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">UglyDuckling</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">Duck</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>

<span class="c1">// ...</span>

<span class="n">UglyDuckling</span><span class="w"> </span><span class="n">uglyDuckling</span><span class="p">;</span>
<span class="n">foo</span><span class="p">(</span><span class="n">uglyDuckling</span><span class="p">);</span>
</pre></div>

<p>We can call <code>foo</code> on an <code>UglyDuckling</code> since <code>UglyDuckling</code> inherits
from <code>Duck</code>. We have an <em>is-a</em> relationship, so we can substitute an
<code>UglyDuckling</code> for a <code>Duck</code>. The problem with this approach is that
whenever we want something that quacks and waddles, we need to inherit
from <code>Duck</code>. More generally, this type of polymorphism is achieved by
implementing a set of interfaces like, for example, <code>IComparable</code>,
<code>IClonebale</code>, <code>IDisposable</code> and so on. This makes things slightly
complicated: what if we need something that waddles, but we don't care
about quacking? Do we separate our duck into two different interfaces?
In general, do we add an interface for each behavior and then pull
groups of interfaces together to form more refined types?</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">IQuack</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Quack</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">IWaddle</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Waddle</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Duck</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">IQuack</span><span class="p">,</span><span class="w"> </span><span class="n">IWaddle</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Quack</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Waddle</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Penguin</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">IWaddle</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Waddle</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>This works, but has combinatorial complexity and we end up with deep
hierarchies which are difficult to reason about. There is another way to
achieve this though, using generic programming:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">UglyDuckling</span><span class="w"> </span><span class="c1">// No inheritance</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Quack</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Waddle</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">Duck</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">foo</span><span class="p">(</span><span class="n">Duck</span><span class="o">&amp;</span><span class="w"> </span><span class="n">duck</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">duck</span><span class="p">.</span><span class="n">Quack</span><span class="p">();</span>
<span class="w">    </span><span class="n">duck</span><span class="p">.</span><span class="n">Waddle</span><span class="p">();</span>
<span class="p">}</span>

<span class="c1">// ...</span>

<span class="n">UglyDuckling</span><span class="w"> </span><span class="n">uglyDuckling</span><span class="p">;</span>
<span class="n">foo</span><span class="p">(</span><span class="n">uglyDuckling</span><span class="p">);</span>
</pre></div>

<p><code>foo</code> here is a templated function which only cares that the type passed
in has a <code>Quack</code> and a <code>Waddle</code> member function. There is no inheritance
involved, but we can still substitute an <code>UglyDuckling</code> for a <code>Duck</code>.
This gets us rid of all the interfaces (we don't need our <code>Penguin</code> to
explicitly implement an <code>IWaddle</code> interface, we just need it to provide
a <code>Waddle</code> member function). Our model becomes simpler - as long as a
type supports the behavior required by a function, it can be used with
that function.</p>

<h2>Mixins</h2>

<p>Lore has it that multiple inheritance is bad and it is by design not
supported in Java, C#, and such. On the other hand, mixins are extremely
useful, and it is a pity that we usually have to express them via
inheritance. A mixin is a type that provides some behavior which is
<em>mixed in</em> or <em>included</em> into another type. For example, if we use
intrusive reference counting, we can isolate the reference-counting
behavior into its own type:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">RefCounted</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">AddRef</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="o">++</span><span class="n">m_refCount</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Release</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">--</span><span class="n">m_refCount</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">delete</span><span class="w"> </span><span class="k">this</span><span class="p">;</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">RefCounted</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">atomic</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_refCount</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Then we can have other types for which we want intrusive reference
counting simply mixing in this behavior:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Foo</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">RefCounted</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
</pre></div>

<p>Now <code>Foo</code> has <code>AddRef</code> and <code>Release</code> functions which can be called by a
generic smart pointer that expects managed types to expose these member
functions. While technically <code>Foo</code> inherits from <code>RefCounted</code>,
conceptually we only care that it includes the reference counting
behavior. In such cases it is perfectly fine to mix and match and
include behavior defined across multiple other types.</p>

<h2>The Case for Free Functions</h2>

<p>What is the difference between the following two <code>Print</code> functions?</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Foo</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Print</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="k">this</span><span class="o">-&gt;</span><span class="n">Data</span><span class="p">();</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">Data</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">Print</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Foo</span><span class="o">&amp;</span><span class="w"> </span><span class="n">foo</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">foo</span><span class="p">.</span><span class="n">Data</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>The first is a member function, called with an implicit <code>this</code> argument
which points to the object instance, while the second is a free function
called with an explicit reference to a <code>Foo</code> object.</p>

<p>The member function approach leads to bloated objects as whenever we
need some additional processing of the type, we would have to add new
member functions. This contradicts the <em>Single Responsibility Principle</em>
which states that each class should have a single responsibility. Adding
member functions like <code>ToString</code>, <code>Serialize</code> etc. needlessly bloats a
class.</p>

<p>In general, we only need member functions when these functions access
private members of the type. If <code>Data</code> was private in the above example,
then the free-function version wouldn't have worked. As long as we can
implement a function that operates on a type without having to access
its private member, that function should not belong to the type.
Depending on the language, we have several options. We could put such
functions in <q>helper</q> types:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">FooPrinter</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Print</span><span class="p">(</span><span class="n">Foo</span><span class="w"> </span><span class="n">foo</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>C# provides extension methods as syntax sugar for this, which allow us
to call <code>foo.Print()</code> even though we implement the <code>Print</code> function as
an extension method:</p>
<div class="highlight"><pre><span/><span class="k">static</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">FooPrinter</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Print</span><span class="p">(</span><span class="k">this</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="n">foo</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Still, the simplest thing to do is have a free function:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">Print</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Foo</span><span class="o">&amp;</span><span class="w"> </span><span class="n">foo</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* ... */</span><span class="w"> </span><span class="p">}</span>
</pre></div>

<p>Being forced to group everything inside classes yields messy code. Steve
Yegge's <a href="http://steve-yegge.blogspot.com/2006/03/execution-in-kingdom-of-nouns.html">Kingdom of
Nouns</a>
is a classic on the topic.</p>

<h3>Managers and Utils</h3>

<p>Because a purely object-oriented language forces developers to think in
classes, we more often than not end up with managers and utility
classes, both being horrible replacements for free-standing functions.</p>

<p>Managers usually show up once we have a nice object model for the
problem space but we need to implement a set of operations on said
object model. Managers tend to be singletons. For example, we have a
<code>Connection</code> type that models a connection to a peer:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Connection</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Open, Close, Send, Receive etc.</span>
<span class="p">}</span>
</pre></div>

<p>We also want someone to open new connections and close all opened
connections. Here is a purely object oriented <code>ConnectionManager</code>:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">ConnectionManager</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">ConnectionManager</span><span class="w"> </span><span class="n">_instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ConnectionManager</span><span class="p">();</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="nf">ConnectionManager</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">ConnectionManager</span><span class="w"> </span><span class="nf">GetInstance</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">_instance</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="n">List</span><span class="o">&lt;</span><span class="n">Connection</span><span class="o">&gt;</span><span class="w"> </span><span class="n">_connections</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">List</span><span class="o">&lt;</span><span class="n">Connection</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">Connection</span><span class="w"> </span><span class="nf">Make</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="kt">var</span><span class="w"> </span><span class="n">connection</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Connection</span><span class="p">();</span>
<span class="w">        </span><span class="n">_connections</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">connection</span><span class="p">);</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">connection</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">CloseAll</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">_connections</span><span class="p">.</span><span class="n">ForEach</span><span class="p">(</span><span class="n">connection</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">connection</span><span class="p">.</span><span class="n">Close</span><span class="p">());</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This maintains the list of connections and can close all of them with
a call to <code>CloseAll()</code>. Besides being verbose to use
(<code>ConnectionManager.GetInstance().Make()</code>,
<code>ConnectionManager.GetInstance().Close()</code>), this class does not make
much sense. A non-OOP implementation would look like this:</p>
<div class="highlight"><pre><span/><span class="c1">// In .h file</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Connection</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Open, Close, Send, Receive etc.</span>
<span class="p">};</span>
<span class="w">Â </span>
<span class="n">Connection</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">Make</span><span class="p">();</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">CloseAll</span><span class="p">();</span>
<span class="w">Â </span>
<span class="c1">// In .cpp file</span>
<span class="k">namespace</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">Connection</span><span class="o">&gt;</span><span class="w"> </span><span class="n">connections</span><span class="p">;</span>
<span class="p">}</span>
<span class="w">Â </span>
<span class="n">Connection</span><span class="o">&amp;</span><span class="w"> </span><span class="n">Make</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">connections</span><span class="p">.</span><span class="n">emplace_back</span><span class="p">(</span><span class="n">Connection</span><span class="p">{});</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">connections</span><span class="p">.</span><span class="n">back</span><span class="p">();</span>
<span class="p">}</span>
<span class="w">Â </span>
<span class="kt">void</span><span class="w"> </span><span class="n">CloseAll</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">connection</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">connections</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">connection</span><span class="p">.</span><span class="n">Close</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p><code>Make()</code> and <code>CloseAll()</code> do not need to be group in some manager.
They can be free functions living next to the <code>Connection</code> type, which
is the only context within which they make sense. The list of
connections can be stored in a variable scoped to the implementation
.cpp file. <q>Managers</q> rarely make sense.</p>

<p>Utility classes are even worse: while a manager is usually tightly
coupled to the type it <q>manages</q>, <q>Utils</q> classes end up being
dumping grounds of functions that don't seem to belong anywhere else.
The biggest problem is that each of these functions usually depends on
some other component:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">FooUtils</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">DoBar</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Dependency on Bar */</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">DoBaz</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Dependency on Baz */</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Now whoever takes a dependency on <code>FooUtils</code>, transitively takes a
dependency on both <code>Bar</code> and <code>Baz</code> too, even if they only really needed
one of them. If <code>DoBar()</code> and <code>DoBaz()</code> were free functions, taking a
dependency on <code>DoBar()</code> would transitively take a dependency on <code>Bar</code>
only. <q>Utility</q> types make layering a nightmare.</p>

<h2>When To Use Classes</h2>

<p>I am a big believer in multi-paradigm. If our only tool is a hammer, we
can only hammer things. While pure functional languages are elegant,
they are too far removed from the machine they run on (for example we
can't implement an in-place <code>reverse</code> if all data is immutable).
Similarly, if everything is an object, we end up with too many classes
and too many complicated relationships. Procedural languages usually
provide some way to group data via <code>struct</code> or <code>record</code> types, so when
are classes useful?</p>

<p>The answer is <em>for encapsulating</em> - classes enable us to declare private
data and control access to it. This is useful when the class needs to
maintain invariants, which could potentially be broken if external
entities would be able to change an object's state. Let's use a <code>Date</code>
type as a made up example. Made up because dates are usually implemented
as a number representing a tick count since some set start date, and
information like <em>day</em>, <em>month</em>, and <em>year</em> is derived from that. But
let's assume we have separate <em>day</em>, <em>month</em>, and <em>year</em> fields. This
type should maintain an invariant that it represents a valid date, so we
can't have, for example, a June 31st. It's hard to enforce the
invariant with:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Date</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">day</span><span class="p">;</span>
<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">month</span><span class="p">;</span>
<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">year</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Alternately, we can implement a class with a constructor which ensures
only valid dates can be created:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Date</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="n">Date</span><span class="p">(</span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">year</span><span class="p">,</span><span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">month</span><span class="p">,</span><span class="w"> </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">day</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">month</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="w"> </span><span class="o">||</span><span class="w"> </span><span class="n">month</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="mi">12</span><span class="p">)</span><span class="w"> </span><span class="k">throw</span><span class="w"> </span><span class="cm">/* ... */</span>
<span class="w">        </span><span class="cm">/* Additional checks to ensure a valid date... */</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">year</span><span class="p">()</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="k">noexcept</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">m_year</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">month</span><span class="p">()</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="k">noexcept</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">m_month</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">day</span><span class="p">()</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="k">noexcept</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">m_day</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">m_day</span><span class="p">;</span>
<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">m_month</span><span class="p">;</span>
<span class="w">    </span><span class="kt">uint8_t</span><span class="w"> </span><span class="n">m_year</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>If we want to add an <code>AddDays</code> function, we would create a member
function <sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup> which would implement the algorithm that would know when
adding a number of days would increment the month and when incrementing
the month would increment the year, such that the invariant of always
having a valid date is enforced.</p>

<p>On the other hand, a type which doesn't need to maintain an invariant,
say a point in the plane, should not be implemented as a class:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Point</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int64_t</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="w">    </span><span class="kt">int64_t</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<h2>Summary</h2>

<p>Inheritance is rarely warranted, and when used, it should mostly be used
in the context of mixins - with the intention of including behavior
rather than deriving and extending. Interfaces are sometimes useful at a
component boundary, though static, template-based polymorphism is
preferred. A good design consists of a set of independent classes which
maintain invariants, and free functions that operate on them. Structure
(or record) types should be used when there is no invariant to be
maintained. Generic functions should be used when algorithms can be
generalized to multiple types as long as they satisfy some requirements
(as in the Duck Typing section above). This encourages reusable code and
systems of loosely-coupled components which can be more easily reasoned
about in isolation and reused when needed.</p>

<ul>
<li>Generic programming/compile-time polymorphism yields less complex
models than inheritance</li>
<li>While multiple inheritance is frowned upon, mixins provide a great
way to add behavior to a type. The problem is including this
behavior is usually syntactically equivalent with inheritance.</li>
<li>Free functions are great. Managers and Utils are bad and should be
avoided.</li>
<li>Classes are useful when invariants need to be enforced.
Encapsulation and member functions maintain invariants.</li>
<li>A good design consists of loosely-coupled components and generic
functions, which can be reasoned about in isolation and freely
combined to create complex behavior.</li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>Or better yet a free function which takes a <code>Date</code> and returns a
new instance - immutability seems like a good idea in this case. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sat, 27 Jan 2018 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/12/30/evens-before-odds.html</link>
      <guid>https://vladris.com/blog/2017/12/30/evens-before-odds.html</guid>
      <title><![CDATA[Evens before Odds]]></title>
      <description><![CDATA[<h1>Evens before Odds</h1>

<p>One of my go-to interview questions goes like this:</p>

<blockquote>
<p>Given an array of numbers, make it so the even numbers come before the
odd ones.</p>

<p>For example, for <code>{ 1, 2, 3, 4, 5, 6, 7, 8 }</code>, a possible output would
be <code>{ 8, 2, 6, 4, 5, 3, 7, 1 }</code>.</p>
</blockquote>

<p>This is not a trick question by any means, it is a straightforward
problem with a couple of straightforward solutions. Note the <em>possible
output</em> wording and the fact that evens and odds in the output do not
preserve the relative order they had in the input.</p>

<h2>A Space-Inefficient Solution</h2>

<p>An easy solution is to traverse the input once and store all even
numbers encountered during the traversal into a separate array, then
traverse it again and do the same for the odd numbers:</p>
<div class="highlight"><pre><span/><span class="k">auto</span><span class="w"> </span><span class="n">evens_before_odds</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="w">    </span><span class="n">result</span><span class="p">.</span><span class="n">reserve</span><span class="p">(</span><span class="n">numbers</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This solves the problem in <code>O(n)</code> linear time (two traversals of the
input array) and <code>O(n)</code> linear space - result is as large as input, so
additional space required grows linearly with the size of the input.</p>

<p>There are more efficient way of doing this in linear time and constant
space.</p>

<h2>Two Algorithms</h2>

<p>There are a couple of ways we can solve this. One algorithm goes like
this:</p>

<blockquote>
<p>Find the first odd number. Stop if we reached the end of the array.</p>

<p>Find the first event number after that odd number. Stop if we reached
the end of the array.</p>

<p>Swap them.</p>

<p>Repeat.</p>
</blockquote>

<p>Our loop invariant is that all numbers before the first odd number
(which we update during each iteration) are already in the right place.
With each iteration, we find another even number that appears after the
first odd number so we swap them, putting the even in the right place.
We stop when we run out of numbers to swap, either odd or even. An
implementation of this algorithm looks like this:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">evens_before_odds</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Find first odd number</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>

<span class="w">        </span><span class="c1">// If we reached the end we're done</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="c1">// Find the first even number after the first odd one</span>
<span class="w">        </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">++</span><span class="n">j</span><span class="p">;</span>

<span class="w">        </span><span class="c1">// If we reached the end we're done</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">j</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="c1">// Swap and continue</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="w">        </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>While the algorithm is fairly straight-forward, the devil is in the
details - we need to perform multiple checks to make sure we don't run
off the end of the array. While interviewing, I've seen many bugs come
up due to missing some of these checks.</p>

<p>An interesting observation we can make is that once we found the first
pair of odd and even numbers, after we swap them, the new first odd
number is right after the even we just swapped, so we can hoist the
first while statement out of the main loop - we only need to find the
first odd once, then we just increment after each swap:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">evens_before_odds</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>

<span class="w">    </span><span class="c1">// Find the first odd number</span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">n</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">        </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// If we reached the end weâre done</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="w">        </span><span class="k">return</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// Start after the first odd and until we reach the end</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">j</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// If itâs an even number</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="c1">// Swap with the first odd</span>
<span class="w">            </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="w">            </span><span class="c1">// Increment first odd position</span>
<span class="w">            </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Another algorithm goes like this:</p>

<blockquote>
<p>Find the first odd number.</p>

<p>From the back, find the last even number.</p>

<p>Stop if the first odd number appears after the last even number.</p>

<p>Swap and repeat.</p>
</blockquote>

<p>Our loop invariant is that all numbers before the first odd and all
numbers after the last even are already in place. With each iteration,
we move the first odd and last even. We stop when the first odd appears
after the last even, which means all evens appear before the odds. Here
is a possible implementation:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">evens_before_odds</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// Find the first odd number</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>

<span class="w">        </span><span class="c1">// If the first odd occurs after the last even, stop</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="c1">// Find the last even number</span>
<span class="w">        </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>

<span class="w">        </span><span class="c1">// If the first odd occurs after the last even, stop</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="c1">// Swap and continue</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="w">        </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Both of the above algorithms solve the problem in linear time and
constant space.</p>

<h3>Test Cases</h3>

<p>Some interesting test cases to validate the implementations:</p>

<ul>
<li>Our example input <code>{1, 2, 3, 4, 5, 6, 7, 8 }</code>.</li>
<li>An empty vector <code>{ }</code>.</li>
<li>A vector with a single even number <code>{ 2 }</code>.</li>
<li>A vector with a single odd number <code>{ 1 }</code>.</li>
<li>A vector consisting of all even number <code>{ 2, 4, 6 }</code>.</li>
<li>A vector consisting of all odd numbers <code>{ 1, 3, 5 }</code>.</li>
</ul>

<h3>Follow Up: Odds before Evens</h3>

<p>My follow up question is</p>

<blockquote>
<p>What if we also want the ability to put odd numbers before even ones?
How would we extend our code?</p>
</blockquote>

<p>An answer I'm <strong>not</strong> looking for is <em>we copy/paste the function, rename
it to</em> <code>odds_before_evens</code> <em>and update the checks</em>.</p>

<p>A clever answer (which I'm also not looking for) is <em>we provide an</em>
<code>odds_before_evens</code> <em>which internally calls</em> <code>evens_before_odds</code> <em>, then
reverses the output</em>:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">odds_before_evens</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">evens_before_odds</span><span class="p">(</span><span class="n">numbers</span><span class="p">);</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">reverse</span><span class="p">(</span><span class="n">numbers</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
<span class="p">}</span>
</pre></div>

<p>A common answer is <em>we add a flag</em>:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">arrange_numbers</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">,</span><span class="w"> </span><span class="kt">bool</span><span class="w"> </span><span class="n">evensFirst</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">((</span><span class="n">evensFirst</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">evensFirst</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)))</span>
<span class="w">            </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">((</span><span class="n">evensFirst</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">evensFirst</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)))</span>
<span class="w">            </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="w">        </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This kind of works, but the condition becomes very complicated.</p>

<h3>Follow Up: Primes before Non-Primes</h3>

<p>What if we also want to move prime numbers before non-prime numbers,
given some <code>bool is_prime(int)</code> primality-testing function?</p>

<p>We can keep adding flags and extending the <code>if</code> conditions:</p>
<div class="highlight"><pre><span/><span class="k">enum</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Arrangement</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">EvensBeforeOdds</span><span class="p">,</span>
<span class="w">    </span><span class="n">OddsBeforeEvens</span><span class="p">,</span>
<span class="w">    </span><span class="n">PrimesBeforeNonPrimes</span><span class="p">,</span>
<span class="p">};</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">arrange_numbers</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">,</span><span class="w"> </span><span class="n">Arrangement</span><span class="w"> </span><span class="n">arrangement</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">((</span><span class="n">arrangement</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">Arrangement</span><span class="o">::</span><span class="n">EvensBeforeOdds</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">arrangement</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">Arrangement</span><span class="o">::</span><span class="n">OddsBeforeEvens</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">arrangement</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">Arrangement</span><span class="o">::</span><span class="n">PrimesBeforeNonPrimes</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">is_prime</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]))))</span>
<span class="w">            </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">((</span><span class="n">arrangement</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">Arrangement</span><span class="o">::</span><span class="n">EvensBeforeOdds</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">arrangement</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">Arrangement</span><span class="o">::</span><span class="n">OddsBeforeEvens</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="o">||</span><span class="w"> </span><span class="p">(</span><span class="n">arrangement</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">Arrangement</span><span class="o">::</span><span class="n">PrimesBeforeNonPrimes</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">!</span><span class="n">is_prime</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]))))</span>
<span class="w">            </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="w">        </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This doesn't scale very well though. What we actually want to do here is
abstract away the predicate based on which we move elements around:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">Pred</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">arrange_numbers</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">pred</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
<span class="w">            </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]))</span>
<span class="w">            </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="w">        </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kt">void</span><span class="w"> </span><span class="n">evens_before_odds</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">arrange_numbers</span><span class="p">(</span><span class="n">numbers</span><span class="p">,</span><span class="w"> </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
<span class="p">}</span>

<span class="kt">void</span><span class="w"> </span><span class="n">odds_before_evens</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">arrange_numbers</span><span class="p">(</span><span class="n">numbers</span><span class="p">,</span><span class="w"> </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
<span class="p">}</span>

<span class="kt">void</span><span class="w"> </span><span class="n">primes_before_non_primes</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">arrange_numbers</span><span class="p">(</span><span class="n">numbers</span><span class="p">,</span><span class="w"> </span><span class="n">is_prime</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Note the algorithm remains the same: we have the exact same steps and
loop invariants, but we can parameterize the condition. With this
abstraction, the code actually becomes smaller and more readable.</p>

<p>This is about as far as I can get during an interview.</p>

<h2>Partition</h2>

<p>This is actually a well-known algorithm called a <em>partitioning
algorithm</em>. A partitioning algorithm moves elements that satisfy a
predicate before elements that don't satisfy it. Let's start with the
above implementation:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">Pred</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">numbers</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span><span class="n">size</span><span class="p">();</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">pred</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
<span class="w">            </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">j</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]))</span>
<span class="w">            </span><span class="o">--</span><span class="n">j</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">j</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="n">numbers</span><span class="p">[</span><span class="n">i</span><span class="p">],</span><span class="w"> </span><span class="n">numbers</span><span class="p">[</span><span class="n">j</span><span class="p">]);</span>
<span class="w">        </span><span class="o">++</span><span class="n">i</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This works for vectors, but what if we want to partition a doubly-linked
list? Can we abstract away the data structure we are partitioning? The
answer is <em>yes</em>. We can use iterators to access the data structure:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Pred</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">))</span>
<span class="w">            </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="o">--</span><span class="n">last</span><span class="p">;</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">last</span><span class="p">))</span>
<span class="w">            </span><span class="o">--</span><span class="n">last</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>

<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">last</span><span class="p">);</span>
<span class="w">        </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>The implementation is virtually the same. We get rid of <code>i</code> and <code>j</code>, as
we are using the iterators provided as arguments for traversal. The
implementation does not increase in complexity, but is now usable beyond
vectors. For example we can now partition a C-style array:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">evens_before_odds</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">arr</span><span class="p">[],</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">partition</span><span class="p">(</span><span class="n">arr</span><span class="p">,</span><span class="w"> </span><span class="n">arr</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
<span class="p">}</span>
</pre></div>

<h3>Useful Return</h3>

<p>A useful return for our algorithm is the <em>partition point</em> - the
position of the first element that does not satisfy our predicate. We
have this implicitly and callers might be interested in it. To avoid
making callers have to recompute it, we should return it:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Pred</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">))</span>
<span class="w">            </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>

<span class="w">        </span><span class="o">--</span><span class="n">last</span><span class="p">;</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">last</span><span class="p">))</span>
<span class="w">            </span><span class="o">--</span><span class="n">last</span><span class="p">;</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>

<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">last</span><span class="p">);</span>
<span class="w">        </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>For example, <code>partition</code> is a key ingredient in quicksort:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Comp</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">quick_sort</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">Comp</span><span class="w"> </span><span class="n">comp</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Stop if we have no elements or one element</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">dist</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">distance</span><span class="p">(</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">last</span><span class="p">);</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">dist</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// Swap pivot with last element</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">pivot</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">dist</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">iter_swap</span><span class="p">(</span><span class="n">pivot</span><span class="p">,</span><span class="w"> </span><span class="o">--</span><span class="n">last</span><span class="p">);</span>

<span class="w">    </span><span class="c1">// Partition around pivot</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="p">[</span><span class="o">&amp;</span><span class="p">](</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">comp</span><span class="p">(</span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">last</span><span class="p">);</span>
<span class="w">    </span><span class="p">});</span>

<span class="w">    </span><span class="c1">// Move pivot back in place</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">iter_swap</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="w"> </span><span class="n">last</span><span class="p">);</span>

<span class="w">    </span><span class="c1">// Recursively sort left and right sides of the pivot</span>
<span class="w">    </span><span class="n">quick_sort</span><span class="p">(</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">p</span><span class="p">,</span><span class="w"> </span><span class="n">comp</span><span class="p">);</span>
<span class="w">    </span><span class="n">quick_sort</span><span class="p">(</span><span class="n">p</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="o">++</span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">comp</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<h3>STL Implementations</h3>

<p>The <code>partition</code> algorithm we ended up with is fairly efficient, but it's
worth taking a look at some of the highly-optimized STL implementations.
This is the MSVC STL implementation:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Pred</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;;</span><span class="w"> </span><span class="o">++</span><span class="n">first</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">);</span><span class="w"> </span><span class="o">++</span><span class="n">first</span><span class="p">);</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>

<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="o">--</span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">last</span><span class="p">););</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>

<span class="w">        </span><span class="n">iter_swap</span><span class="p">(</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">last</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Note this performs the least possible amount of operations. It also
seems to favor <code>for</code> loops. Contrast this with the LLVM libc++
implementation, which seems to favor <code>while</code> loops:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Pred</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nb">true</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nb">true</span><span class="p">)</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">))</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w">            </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">        </span><span class="k">do</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="o">--</span><span class="n">last</span><span class="p">)</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">last</span><span class="p">));</span>
<span class="w">        </span><span class="n">swap</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">last</span><span class="p">);</span>
<span class="w">        </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<h3>Iterator Requirements and Complexity</h3>

<p>We focused on the second algorithm presented, which finds the first odd,
last even, and swaps them. We had another algorithm which was looking
for <em>the first even after the first odd</em> during each iteration. Let's
provide a generic implementation for it too:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Pred</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">))</span>
<span class="w">        </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">next</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">next</span><span class="p">(</span><span class="n">first</span><span class="p">);</span><span class="w"> </span><span class="n">next</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">next</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">next</span><span class="p">))</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="n">std</span><span class="o">::</span><span class="n">swap</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">next</span><span class="p">);</span>
<span class="w">            </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>What is the difference?</p>

<p>The difference is that this algorithm only ever increments the
iterators. That means it only requires a <code>ForwardIterator</code>, as opposed
to the other algorithm, which finds the <em>last even</em> number starting from
the <code>last</code> iterator, which requires a <code>BidirectionalIterator</code>.</p>

<p>In other words, the algorithm requiring only a <code>ForwardIterator</code> works
on a singly-linked list (<code>forward_list</code>), while the other one can't (we
can only traverse a singly-linked list forward in <code>O(1)</code> time, not
backwards).</p>

<p>The MSVC STL implementation of the forward-iterator algorithm is:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Pred</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">))</span>
<span class="w">        </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>

<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">next</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">next</span><span class="p">(</span><span class="n">first</span><span class="p">);</span><span class="w"> </span><span class="n">next</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">next</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">next</span><span class="p">))</span>
<span class="w">            </span><span class="n">iter_swap</span><span class="p">(</span><span class="n">first</span><span class="o">++</span><span class="p">,</span><span class="w"> </span><span class="n">next</span><span class="p">);</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The libc++ one is:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">It</span><span class="p">,</span><span class="w"> </span><span class="n">tpyename</span><span class="w"> </span><span class="n">Pred</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">partition</span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">It</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">Pred</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="nb">true</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">))</span>
<span class="w">            </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">It</span><span class="w"> </span><span class="n">next</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">first</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">next</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="p">;)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pred</span><span class="p">(</span><span class="o">*</span><span class="n">next</span><span class="p">))</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="n">swap</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">next</span><span class="p">);</span>
<span class="w">            </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The reason both implementations are provided is that the
<code>ForwardIterator</code> version, while more generally applicable, is slightly
less efficient. The <code>BidirectionalIterator</code> version moves any element at
most once, and since the move is a swap, it means it performs at most
<code>N / 2</code> swaps where <code>N</code> is the number of elements. The <code>ForwardIterator</code>
version might perform more swaps, up to <code>N</code>. For example, for the input
<code>1 2 4</code>, during the first step, it would swap <code>1</code> with <code>2</code>, ending up
with <code>2 1 4</code>, then during the next step it would swap <code>1</code> with <code>4</code>,
ending up with <code>2 4 1</code>.</p>

<h2>In C</h2>

<p>Partitioning is not specific to the C++ language. The same
implementation can be used, for example, in C#, up to abstracting away
data structure traversal:</p>
<div class="highlight"><pre><span/><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">IListPartition</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">Partition</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="k">this</span><span class="w"> </span><span class="n">IList</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">self</span><span class="p">,</span><span class="w"> </span><span class="n">Func</span><span class="o">&lt;</span><span class="n">T</span><span class="p">,</span><span class="w"> </span><span class="kt">bool</span><span class="o">&gt;</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">self</span><span class="p">.</span><span class="n">Count</span><span class="p">;</span>

<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(;;)</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">pred</span><span class="p">(</span><span class="n">self</span><span class="p">[</span><span class="n">first</span><span class="p">]))</span>
<span class="w">                </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">                </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>

<span class="w">            </span><span class="o">--</span><span class="n">last</span><span class="p">;</span>
<span class="w">            </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="o">!</span><span class="n">pred</span><span class="p">(</span><span class="n">self</span><span class="p">[</span><span class="n">last</span><span class="p">]))</span>
<span class="w">                </span><span class="o">--</span><span class="n">last</span><span class="p">;</span>

<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">first</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">last</span><span class="p">)</span>
<span class="w">                </span><span class="k">return</span><span class="w"> </span><span class="n">first</span><span class="p">;</span>

<span class="w">            </span><span class="kt">var</span><span class="w"> </span><span class="n">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">self</span><span class="p">[</span><span class="n">first</span><span class="p">];</span>
<span class="w">            </span><span class="n">self</span><span class="p">[</span><span class="n">first</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">self</span><span class="p">[</span><span class="n">last</span><span class="p">];</span>
<span class="w">            </span><span class="n">self</span><span class="p">[</span><span class="n">last</span><span class="p">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">temp</span><span class="p">;</span>
<span class="w">            </span><span class="o">++</span><span class="n">first</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>The .NET <code>IEnumerator</code> does not allow us to mutate the data structure we
are enumerating over, so we cannot provide a generic <code>IEnumerable&lt;T&gt;</code>
partition algorithm that works in-place. Otherwise the implementation is
pretty much identical to the C++ one, as the algorithm is the same.</p>

<h2>Summary</h2>

<ul>
<li>Moving even numbers before odd ones in a given array of numbers is
an instance of partition.</li>
<li>The algorithm can be generalized to work with an arbitrary
predicate.</li>
<li>The algorithm can be generalized to work across any data structure
as long as it can be traversed with at least a <code>ForwardIterator</code>.</li>
<li>A <code>BidirectionalIterator</code> version performs at most <code>N / 2</code> swaps
(and <code>N</code> applications of the predicate).</li>
<li>A <code>ForwardIterator</code> version performs at most <code>N</code> swaps (and <code>N</code>
applications of the predicate).</li>
<li>Both versions of the algorithm are part of the standard library
(<code>std::partition</code> algorithm).</li>
<li>The same algorithm can be implemented in other languages, as generic
as the available abstractions allow.</li>
</ul>
]]></description>
      <pubDate>Sat, 30 Dec 2017 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/12/10/binary-relations.html</link>
      <guid>https://vladris.com/blog/2017/12/10/binary-relations.html</guid>
      <title><![CDATA[Binary Relations]]></title>
      <description><![CDATA[<h1>Binary Relations</h1>

<h2>Definitions</h2>

<p>Given a set of objects <code>A</code>, a binary relation <code>R</code> on the set is defined
as a subset of <code>A x A</code>. The <em>characteristic function</em> <code>r</code> for <code>R</code> is the
function <code>r : A x A -&gt; bool</code> such that <code>r(x, y)</code> is <code>true</code> if
<code>(x, y) in R</code>, and <code>false</code> if <code>(x, y) not in R</code>. For a more natural
notation, we can use <code>x ~ y</code> to denote <code>r(x, y)</code>.</p>

<p>More generally, a binary relation can be defined on a pair of sets
<code>A x B</code> but to keep things simple, we'll only cover binary relations
over a single set.</p>

<p>Binary relations may have several properties. A few interesting ones
are:</p>

<ul>
<li>A binary relation is <em>reflexive</em> if for any <code>x</code> in <code>A</code>, <code>x ~ x</code>.</li>
<li>A binary relation is <em>strict</em> or <em>irreflexive</em> if there is no <code>x</code> in
<code>A</code> for which <code>x ~ x</code>.</li>
<li>A binary relation is <em>symmetric</em> if for any <code>x, y</code> in <code>A</code>, <code>x ~ y</code>
implies <code>y ~ x</code>.</li>
<li>A binary relation is <em>antisymmetric</em> if for any <code>x, y</code> in <code>A</code>,
<code>x ~ y</code> and <code>y ~ x</code> implies <code>x = y</code>.</li>
<li>A binary relation is <em>transitive</em> if for any <code>x, y, z</code> in <code>A</code>, if
<code>x ~ y</code> and <code>y ~ z</code>, then <code>x ~ z</code>.</li>
<li>A binary relation is <em>total</em> if for any <code>x, y</code> in <code>A</code>, either
<code>x ~ y</code>, <code>y ~ x</code>, or both (in other words, for any <code>x, y</code>, <code>~</code>
imposes some relation between them).</li>
</ul>

<h3>Examples</h3>

<p>The relation <em>is in the subtree rooted at</em> is a reflexive relation where
<code>A</code> is the set of nodes of a tree. For any pair of nodes <code>x</code> and <code>y</code>, we
can establish whether <code>x</code> is in the subtree rooted at <code>y</code> or not, and
for any <code>x</code>, <code>x ~ x</code> is <code>true</code>.</p>

<p>The relation <em>is parent of</em> in a tree is a strict relation: for any <code>x</code>
in the set of tree nodes <code>A</code>, <code>x</code> cannot be a parent of itself.</p>

<p>The relation <em>edge between</em> over the vertices of a non-directed graph is
a symmetric relation: for any <code>x</code> and <code>y</code> vertices of the graph, if
there is an edge from <code>x</code> to <code>y</code>, the same edge exists from <code>y</code> to <code>x</code>,
in other words, if <code>x ~ y</code> then <code>y ~ x</code>.</p>

<p>The <em>is in the subtree rooted at</em> relation above is also antisymmetric:
if for a pair of nodes we can say <code>x</code> is in the subtree rooted at <code>y</code>
and also <code>y</code> is in the subtree rooted at <code>x</code>, it's obvious that both
<code>x</code> and <code>y</code> are, in fact, the root of the subtree, thus <code>x ~ y</code>.</p>

<p>The relation <em>is reachable from</em> over the vertices of a directed graph
is a transitive relation: if <code>x</code> is reachable from <code>y</code> and <code>y</code> is
reachable from <code>z</code>, then <code>x</code> is reachable from <code>z</code>.</p>

<p>All of the above examples are of total relations. An example of a
non-total relation is <em>is ancestor of</em> in a tree. <code>x</code> can be an ancestor
of <code>y</code>, in which case <code>x ~ y</code>, or <code>y</code> can be an ancestor of <code>x</code>, in
which case <code>y ~ x</code>, but it could also be that <code>x</code> and <code>y</code> are in
different subtrees, so neither <code>x ~ y</code> nor <code>y ~ x</code> holds.</p>

<h2>Preorder</h2>

<p>A <em>preorder</em> is a relation which is reflexive and transitive.</p>

<p>A preorder which is also symmetric is an <em>equivalence</em>. A preorder which
is antisymmetric is a <em>partial order</em>. More on those below.</p>

<p>An example of preorder is the <em>is reachable from</em> relation over a
directed graph in the example above. This relation is obviously
reflexive and transitive, but it is neither symmetric nor antisymmetric.
If <code>x</code> is reachable from <code>y</code>, it doesn't mean that <code>y</code> is reachable
from <code>x</code>, so symmetry is not guaranteed. Similarly, if <code>x</code> is reachable
from <code>y</code> and <code>y</code> is reachable from <code>x</code>, it does not mean that <code>y</code> equals
<code>x</code>.</p>

<h2>Equivalence and Equality</h2>

<p>An <em>equivalence</em> relation <code>~</code> is a binary relation that is reflexive,
symmetric, and transitive. In other words, it is a preorder which also
has the symmetric property.</p>

<p>Such a relation partitions the set over which it is defined into
<em>equivalence classes</em> - groups of objects that are equivalent based on
the relation.</p>

<p>An example of equivalence is <em>same month</em> over a set of dates. This
relation is reflexive, since a date <code>d</code> has the same month as itself
(<code>d ~ d</code>); is symmetric, since if <code>d1</code> has the same month as <code>d2</code>, then
<code>d2</code> has the same month as <code>d1</code> (<code>d1 ~ d2 =&gt; d2 ~ d1</code>); and transitive,
since if <code>d1 ~ d2 and d2 ~ d3 =&gt; d1 ~ d3</code>.</p>

<p>This relation partitions our set of dates in the equivalence classes
corresponding to <em>dates in January</em>, <em>dates in February</em>, and so on.
Note that the dates for which the relation holds are equivalent, but not
necessarily equal.</p>

<p>An <em>equality</em> relation is an equivalence relation which partitions the
set <code>A</code> consisting of <code>n</code> objects into exactly <code>n</code> equivalence classes.
In other words, for any <code>x</code> in <code>A</code>, only <code>x ~ x</code> is <code>true</code>.</p>

<h2>Partial Order and Total Order</h2>

<p>A <em>partial order</em> relation <code>&lt;=</code> is a binary relation that is reflexive,
antisymmetric, and transitive. In other words, it is a preorder which
also has the antisymmetric property.</p>

<p>An example of a partial order is the <em>is subset of</em> relation. It is
reflexive (<code>A</code> is a subset of <code>A</code>), antisymmetric (if <code>A</code> is a subset of
<code>B</code> and <code>B</code> is a subset of <code>A</code>, then <code>A = B</code>), and transitive (if <code>A</code> is
a subset of <code>B</code> and <code>B</code> is a subset of <code>C</code>, then <code>A</code> is a subset of
<code>C</code>).</p>

<p>A <em>total order</em> relation is a partial order that is also total. The
above example relation <em>is subset of</em> is not total - there could be a
pair of sets <code>A</code> and <code>B</code> such that neither is the subset of the other.</p>

<p>An example of a total order relation is <em>less than or equal to</em> for
integers.</p>

<h2>Weak Order and Strict Weak Order</h2>

<p>A <em>weak order</em> relation <code>~</code> is a binary relation that is transitive and
total. This implies reflexivity (for any <code>x</code> and <code>y</code>, either <code>x ~ y</code>,
<code>y ~ x</code>, or both, so for <code>x</code> and <code>x</code> we have <code>x ~ x</code>). In other words,
it is a preorder which is also total.</p>

<p>An example of a weak order is <em>less than or equal absolute value</em> for
complex numbers. For any two complex numbers <code>c1</code> and <code>c2</code>, either
<code>c1 ~ c2</code> ( <code>|c1| &lt;= |c2|</code>), <code>c2 ~ c1</code> (<code>|c2| &lt;= |c1|</code>), or both, so <code>~</code>
is total. We also have <code>c1 ~ c2</code> and <code>c2 ~ c3</code> implies <code>c1 ~ c3</code>
(<code>|c1| &lt;= |c2|</code> and <code>|c2| &lt;= |c3|</code> implies <code>|c1| &lt;= |c3|</code>). Unlike a
total order though, the relation is not antisymmetric. We can have
<code>c1 ~ c2</code>, <code>c2 ~ c1</code>, with <code>c1</code> and <code>c2</code> distinct complex numbers (any
two numbers with the same absolute value but different components).</p>

<p>A <em>strict weak order</em> relation <code>&lt;</code> is a binary relation that is
transitive and strict (irreflexive).</p>

<p>An example of strict weak order is <em>less than</em> for integers.</p>

<h2>Applications</h2>

<p>Most programming languages provide a way to customize equality,
inequality, and comparison operators (<code>==</code>, <code>!=</code>, <code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, <code>&gt;=</code>).
There is an interesting point to be made about what equality <em>means</em> in
this context. For some types, this can simply mean comparing the bits
and if they are the same, the objects are equal. But we also have
<em>logical equality</em> - two objects can have different bitwise values but
still be considered equal. Even more so for comparing objects -
comparing bit representations usually does not translate to a meaningful
comparison of objects.</p>

<p>Note though that any other function <code>bool r(const T&amp; m1, const T&amp; m2)</code>
or member function <code>bool r(const T&amp; other)</code> of <code>T</code> denotes a binary
relation on <code>T</code>.</p>

<p>Different algorithms require different types of relations to exist
between objects.</p>

<p>For example, we need at least a partial order relation to perform a
topological sort. That is, in an directed acyclic graph, we can sort the
vertices such that for every edge from <code>a</code> to <code>b</code>, <code>a</code> precedes <code>b</code> in
the order. This can be used, for example, on the dependency graph in a
makefile to determine how to sequence work.</p>

<p>Having an equivalence relation (eg. <code>==</code>), we can implement a linear
search algorithm to traverse a data structure and find an object
equivalent to a given object. The C++ standard library algorithm <code>find</code>
is an example of such an algorithm.</p>

<p>Having a total order relation (eg. <code>&lt;=</code>) or a strict weak order (eg.
<code>&lt;</code>), allows us to implement binary search over an ordered set of
objects. A total order or strict weak order relation also enables
comparison sort algorithms.</p>

<p>Similarly, we need a total order or strict weak order to be able to
determine a minimum or a maximum element from a set of objects
(<code>min_element</code> and <code>max_element</code> algorithms in C++).</p>

<h2>Summary</h2>

<ul>
<li>A binary relation <code>R</code> on a set <code>A</code> is a subset of <code>A x A</code>, denoted
by a characterisitc function <code>r : A x A -&gt; bool</code>.</li>
<li>A binary relation on a type <code>T</code> is denoted by either a free function
of the the form <code>bool r(const T&amp;, const T&amp;)</code> or a member function
<code>bool r(const T&amp;)</code>.</li>
<li>A binary relations may have several properties: it can be reflexive
or strict, symmetric or antisymmetric, transitive, total etc.</li>
<li>Depending on the properties it has, a relation can be, for example:

<ul>
<li>A preorder (reflexive and transitive).</li>
<li>An equivalence (reflexive, symmetric, and transitive).</li>
<li>A partial order (reflexive, antisymmetric, and transitive).</li>
<li>A weak order (reflexive, transitive, and total).</li>
<li>A strict weak order (irreflexive, transitive, and total).</li>
</ul></li>
<li>Certain algorithms require the types they operate on to have
relations with certain properties.</li>
</ul>
]]></description>
      <pubDate>Sun, 10 Dec 2017 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/11/09/notes-on-unit-testing.html</link>
      <guid>https://vladris.com/blog/2017/11/09/notes-on-unit-testing.html</guid>
      <title><![CDATA[Notes on Unit Testing]]></title>
      <description><![CDATA[<h1>Notes on Unit Testing</h1>

<p>This post covers my view on unit testing, why they are important, how to
make time for them, how much to test, and why I don't believe in TDD.
It draws from my personal experience working on multiple software
projects, small and large, both on new code and legacy code, practices I
tried to apply, what worked well and not so well. While it is more
highlevel and I do not provide code snippets, this is by no means a
purely theoretical essay.</p>

<h2>The <q>not enough time</q> fallacy</h2>

<p>Engineers and engineering teams who are not <q>bought</q> on unit testing
use the excuse that there is not enough time to write unit tests. There
is always a deadline or pressure to ship and unit tests, not being
<q>product</q> code, get lower priority.</p>

<p>The problem is that we never get it right the first time - as we get a
better understanding of our problem space, we need to refine our
solution, which includes refactoring to better structure the code and
redesign to accommodate for new requirements. This is where unit tests
become invaluable in ensuring that such radical alterations of the
codebase can be made safely and easily.</p>

<p>What I noticed first hand is that a team who is not disciplined about
testing starts by churning out a significant amount of code but over
surprisingly little time development slows down to a crawl because there
is a lot of manual testing involved in validating any change, nasty bugs
come up, and since refactoring is now scary (who knows what will
break?), engineering debt keeps building up. On the other hand, teams
that author unit tests from the very beginning can maintain a steady
development pace indefinitely.</p>

<p>The funny thing is that engineers who worked in a code base with good
test coverage could never go back - they immediately see the benefits
and are sold on the practice - while engineers who haven't done it know
the theory, pay lip service to it, but never have time to actually
implement tests.</p>

<h2>Making time</h2>

<p>There is, unfortunately, never enough time to do the right thing. My
advice is to make time: unit tests are part of feature development, so
they should be accounted for as such. Do not have separate tasks for
implementing the feature and writing the unit tests - these unit testing
tasks are prime candidates to be deprioritized and cut, after all, the
feature <em>works</em>, right? Instead consider testing as part of
implementation, create a single task, and adjust estimates accordingly.
There is always pressure to ship, the job of a good engineer is to not
cave under this pressure, set expectations, and deliver a robust
solution. As mentioned above, the ability to keep a steady development
pace makes the average cost of authoring tests over time seem like
nothing compared to the alternative - a steady drop in development
agility.</p>

<p>Advice to managers is to encourage a culture of quality and best
practices. Strategically, shipping next week vs the week after is not as
important as shipping in a couple of months vs shipping in a year, which
is where the brittleness of the codebase becomes a major factor. Reward
good engineering practices and you end up with well-engineered code.</p>

<p>That being, sometimes we <em>do</em> need to ship next week.</p>

<h2>MQs</h2>

<p>In the old waterfall development days, we had several major milestones,
each spanning months of development: M1, M2 etc. As ship date came near,
pressure increased, and shortcuts were taken more often. In the end,
ship dates were met, but with a lot of compromises. What followed right
after, when the team was burned out after the final stretch, was the so
call <q>quality milestone</q> or MQ. Here, engineers were free to reduce
debt while project managers went to define the future version of the
product.</p>

<p>I personally love the concept of MQ. While I don't doubt the existence
of <em>purely agile</em> teams where everything is delivered after week-long
sprints with high quality, most businesses make promises to customers
and must meet deadlines. Sometimes the pressure increases enough that we
knowingly take engineering shortcuts:</p>

<blockquote>
<p>If I had a week, I'd do it the right way, but this works for now.
I'll come back and fix it later.</p>

<p><em>- Every programmer in the world at some point</em></p>
</blockquote>

<p>After a hard deadline it's the perfect time to schedule a mini-MQ -
spend a week or two recovering from burnout and reducing debt.</p>

<p>This expands beyond unit tests to things like refactoring and
rearchitecting code, automating manual processes, writing documentation
etc.</p>

<h2>The Test-Driven Development fallacy</h2>

<p>The other extreme is test-driven development. The premise of test-driven
development is that turning requirements into unit tests, then writing
code to make those tests pass is a solid approach to engineering. This
sounds great in theory but falls flat in practice.</p>

<p>Good software is correct, efficient, and maintainable. These qualities
come from a good understanding of the problem being solved and a
thought-through solution, not by making a set of test cases pass. An
anecdote I like to reference when discussing this is the Sudoku solver.
Ron Jeffries, one of the founders of extreme programming, wrote several
blog posts in which he attempted to implement a Sudoku solver using
test-driven development
<a href="http://xprogramming.com/articles/sudokumusings">here</a>,
<a href="http://xprogramming.com/articles/oksudoku">here</a>,
<a href="http://xprogramming.com/articles/sudoku2">here</a>,
<a href="http://xprogramming.com/articles/sudoku4">here</a>,
<a href="http://xprogramming.com/articles/sudoku5">here</a>, and
<a href="http://xprogramming.com/articles/roroncemore/">here</a>. The attempt
failed. Around the same time, Peter Norvig implemented a Sudoku solver
and wrote a <a href="http://norvig.com/sudoku.html">blog post</a> with a beautiful
explanation of a thorough approach to analyzing the problem and coming
up with a good algorithm to solve it. The point here is that a set of
unit tests, no matter how comprehensive, will not design an algorithm
for you. The algorithm comes from stepping back and thinking about the
problem, which a test-centric approach actively discourages.</p>

<p>The one good thing that TDD encourages is writing tests which initially
fail, then providing the implementation to make them pass, which ensures
the tests themselves are correct. We can always create a test that
exercises a function and then asserts a tautology
(<code>Assert.IsTrue(true)</code>), which covers the code, makes the test pass, but
provides zero value. Having a test that fails when invoked with a stub
and passes when invoked with the real implementation avoids this issue.</p>

<h2>Tests are about behavior, not design</h2>

<p>Almost forgotten across the industry nowadays is that software can be
formally proven correct. A given number of passing tests can only
guarantee that for that particular set of inputs, we get the expected
output - which, in case of test bugs, might not mean anything. The way
to be 100% confident that the code does what we think it does is to
prove this fact formally. This is not always feasible at scale, but for
critical pieces of functionality, formalism is better than test cases.</p>

<p>That doesn't mean tests are not needed - as soon as a line of code
changes (bug fix, optimization, etc.), the formalism must be
re-evaluated, and, outside fringe programming languages, we can't
automatically detect when a proof no longer holds. The point is that
tests are about behavior not about design - we design to solve the
problem, we test to make sure that our solution does what we expect it
to do. <strong>Design comes first, tests come second, implementation is
third.</strong></p>

<p>Unit tests become valuable when we can make deep changes within our code
and ensure there is no observable change in output. This is invaluable
to engineering velocity.</p>

<h2>How much is enough?</h2>

<p>In terms of code coverage, I believe something around 90% can easily be
achieved with a minimum of effort. Full coverage is unrealistic because
the code always has some interaction with the world - making network
calls, relying on time, random numbers, IO etc. These are all
interactions that can sporadically fail and unit tests, by definition,
must be 100% reliable. A testable design abstracts all the world
interactions under interfaces that can be mocked during testing. This
way, we end up with a thin layer that implements these interfaces and
forwards to the real OS/library functions. This thin layer should not
contain any logic beyond forwarding arguments since it is not really
testable and attempting to write unit tests against it ends up with an
ongoing cost of analyzing random test breaks due to failures in
components outside of our control. The other place where ROI is small is
testing trivial code like getters/setters. This is wasted engineering
effort and provides questionably little value. That being said, this
layer should be at most 10% of the code base, more likely somewhere in
the 1-2% range for larger projects. Everything else should be covered by
unit tests.</p>

<p>There is also an interesting distinction between explicit vs implicit
testing -a function can be covered explicitly, by writing unit tests
against it, or implicitly, by writing unit tests against other functions
that end up calling this function. A good rule of thumb is to test
against the interface not against the private implementation. If you
can't reach the same amount of code coverage by testing the public
interface as you can by testing the implementation details, it means you
have dead code in the implementation - code that cannot be reached from
the public interface for any possible input. This code should be removed
not tested. Unit tests have a cost themselves - if we have tests
exercising a function and, during a refactoring, we change the signature
of that function, we have to go update all these tests. If any
refactoring we make breaks unit tests and requires us to fix them,
engineering cost of maintaining test coverage is increased needlessly.</p>

<p>Ideally, we should break and have to update tests when we break the
interface (the unit's contract to the outside world). We should be able
to freely move the implementation guts around, as keeping tests green in
this case is the ultimate purpose of unit testing - ensuring output
through the contract doesn't break during internal changes. A couple of
gotchas here: if we feel we need to test an implementation detail
because it's scarily complex, we have a code smell - that
implementation detail should be split into multiple, less scary pieces;
if we have a lot of implementation logic underneath a thin interface, we
have another smell - the component (unit) is too clever and should be
split into multiple components, which would necessarily pull some of the
code to the interface level.</p>

<p>The bottom line is that we can achieve +90% test coverage without taking
dependencies on implementation details.</p>

<h2>Ease of testing</h2>

<p>Unit testing must be easy.</p>

<p>Authoring unit tests should be cheap. Running unit tests should be fast
and 100% reliable. Unit tests should be part of the engineering
inner-loop -code/compile/unit test. Code coverage should be easy to
measure. Mocking should be easy. If any of these points fall short, test
coverage suffers. Good infrastructure makes it easy to author and
execute unit tests. This is key in encouraging a team to use good
engineering practices.</p>

<p>The other aspect of testing cost is design - code that is well
componentized is easily testable. Monolithic code, code that implements
lots of branching for various conditions, code that directly calls
components outside of our control (network, UI etc.), are all hard to
test. This is not an excuse to bypass testing, it's a smell of the code
itself.</p>

<h2>Learned hopelessness</h2>

<p>It's easy to agree with all of the above but resign yourself to the
fact that in your organization things are different - the infrastructure
is not there, the culture is not there, there is no time. I believe that
the most successful and long-lived software projects have a codebase
ridden with compromises and outdated software practices, which is not a
symptom of any problem, it's the result of implementing a successful
business. It is our duty as software craftsman to remove the compromises
and update the outdated practices, question the status quo and strive to
make things better. Write unit tests!</p>
]]></description>
      <pubDate>Thu, 09 Nov 2017 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/08/13/24.html</link>
      <guid>https://vladris.com/blog/2017/08/13/24.html</guid>
      <title><![CDATA[24]]></title>
      <description><![CDATA[<h1>24</h1>

<p>I recently learned about the <a href="https://en.wikipedia.org/wiki/24_Game">24
game</a>. There are several variants
of it, but the version I learned goes like this:</p>

<blockquote>
<p>Take out the face cards and jokers from a deck and deal four cards
(aces or number cards). Aces can be used either as 1 or as 11. Using
addition, subtraction, multiplication, and division, with any grouping
of operations (paranthesis can be added anywhere), try to come up with
an expression that uses all four cards once and equals 24. Division is
fractional, so <code>5 / 2</code> is <code>2.5</code>.</p>

<p>For example for <code>A 4 5 8</code> we have \((1 + 5) * (8 - 4)\).</p>
</blockquote>

<p>There is the problem of implementing an algorithm to find a solution
given the cards as input.</p>

<h2>Brute force</h2>

<p>A simple solution is to try all permutations of cards, all possible
operations, and all possible groupings.</p>

<p>In the general case, there are 24 ways to arrange the cards -
permutations of 4 which is <code>4!</code>. Each ace doubles this number as we need
to consider the case in which we use it as 1 and the case in which we
use it as 11.</p>

<p>There are 64 ways to combine operations, since we have 4 operations in 3
possitions, which means \(4^3\) total.</p>

<p>We also have 5 possible groupings:</p>

<p>\[(x_0 \odot x_1) \oplus (x_2 \otimes x_3)\]\[((x_0 \odot x_1) \oplus x_2) \otimes x_3\]\[(x_0 \odot (x_1 \oplus x_2)) \otimes x_3\]\[x_0 \odot ((x_1 \oplus x_2) \otimes x_3)\]\[x_0 \odot (x_1 \oplus (x_2 \otimes x_3))\]</p>

<p>where \(\odot, \oplus, \otimes\) are placeholders for any operators (they
could potentially be the same operator).</p>

<p>A simple solver implementation looks like this:</p>
<div class="highlight"><pre><span/><span class="kn">from</span><span class="w"> </span><span class="nn">itertools</span><span class="w"> </span><span class="kn">import</span> <span class="n">permutations</span><span class="p">,</span> <span class="n">product</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sys</span><span class="w"> </span><span class="kn">import</span> <span class="n">argv</span>

<span class="c1">## Transform arguments to numbers, replace 'A' and 'a' with [1, 11]</span>
<span class="n">args</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">11</span><span class="p">]</span> <span class="k">if</span> <span class="n">arg</span> <span class="ow">in</span> <span class="s1">'aA'</span> <span class="k">else</span>
    <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">arg</span><span class="p">)]</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">5</span><span class="p">]],</span> <span class="p">[])</span>

<span class="c1">## For every permutation of 4 arguments</span>
<span class="k">for</span> <span class="n">xs</span> <span class="ow">in</span> <span class="n">permutations</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="mi">4</span><span class="p">):</span>
    <span class="c1"># If we have more 1s and 11s then aces ignore this permutation</span>
    <span class="k">if</span> <span class="nb">sum</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">11</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">xs</span><span class="p">)</span> <span class="o">&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="o">-</span> <span class="mi">4</span><span class="p">:</span>
        <span class="k">continue</span>

    <span class="c1"># For every possible combination of 3 operators</span>
    <span class="k">for</span> <span class="n">ops</span> <span class="ow">in</span> <span class="n">product</span><span class="p">(</span><span class="s1">'+-*/'</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="mi">3</span><span class="p">):</span>
        <span class="c1"># For every possible grouping</span>
        <span class="k">for</span> <span class="n">exp</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'(</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> (</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">)'</span><span class="p">,</span>
                    <span class="s1">'((</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">'</span><span class="p">,</span>
                    <span class="s1">'(</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> (</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">)) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">'</span><span class="p">,</span>
                    <span class="s1">'</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> (</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> (</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">))'</span><span class="p">,</span>
                    <span class="s1">'</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> ((</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">)'</span><span class="p">]:</span>

            <span class="c1"># Place operands and operators in expression</span>
            <span class="n">exp</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">xs</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">ops</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">xs</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">ops</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">xs</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span>
                <span class="n">ops</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">xs</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>

            <span class="k">try</span><span class="p">:</span>
                <span class="c1"># If expression evaluates to 24, we found a solution</span>
                <span class="k">if</span> <span class="nb">eval</span><span class="p">(</span><span class="n">exp</span><span class="p">)</span> <span class="o">==</span> <span class="mi">24</span><span class="p">:</span>
                    <span class="nb">print</span><span class="p">(</span><span class="n">exp</span><span class="p">)</span>
                    <span class="n">exit</span><span class="p">()</span>
            <span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
                <span class="c1"># Ignore division by zero errors</span>
                <span class="k">pass</span>

<span class="c1">## If we get here we tried all combinations and couldn't</span>
<span class="c1">## find any solution</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">'No solution'</span><span class="p">)</span>
</pre></div>

<p>We have ten possible cards (ace and number cards), and taking
combination with repetition of 4 cards, we have
\(\frac{(n + r - 1)!}{r! * (n - 1)!}\) for \(n = 10, r = 4\), so a total of
\(\frac{(10 + 4 - 1)!}{4! * (10 - 1)!}
= 715\) possible games.</p>

<p>Feeding all possible games to the code above, we can see that there are
117 games which have no solution. The remaining 598 games are solvable.</p>

<p>We can optimize the above solution further by observing that we only
need three of the five groupings to cover all cases. Take, for example,
\(x_0 \odot ((x_1 \oplus x_2) \otimes x_3)\). Now if \(\odot\) is a
commutative operation (addition or multiplication), we can rewrite this
to the equivalent \(((x_1 \oplus x_2) \otimes x_3) \odot x_0\), and since
we any way take all permuations of arguments and operators, this ends up
getting covered by the \(((x_0 \odot x_1) \oplus x_2) \otimes x_3\) case.
For non-commutative operations, for example subtraction, notice that if
we do have a solution \(x_0 - ((x_1 \oplus x_2) \otimes x_3) = 24\), since
\(x_0\) is at most 11, it means we need to subtract a negative number from
it in order to get 24. This implies that at least \(\oplus\) or \(\otimes\)
is also a subtraction. If \(\otimes\) is a subtraction, we can rewrite the
expression \(x_0 - ((x_1 \oplus x_2) - x_3)\) as \((x_0 + x_3) -
(x_1 \oplus x_2)\). If \(\otimes\) is not a subtraction but \(\oplus\) is, we
have \(x_0 - ((x_1 - x_2) \otimes x_3)\) which is equivalent with
\(x_0 - (- (x_2 - x_1) \otimes x_3)\). If \(\otimes\) is addition, this
becomes \(x_0 - (x_3 - (x_2 - x_1))\) = \((x_0 - x_3) + (x_2 - x_1)\). If
\(\otimes\) is multiplication or division, this becomes \(x_0 - (-
(x_2 - x_1) \otimes x_3)\) = \(x_0 + ((x_2 - x_1) \otimes x_3)\) =
\(((x_2 - x_1) \otimes x_3) + x_0\).</p>

<p>Similar rewrites can be done if \(\odot\) is division by observing that we
would have to divide with a fractional number in order to get 24, so at
least one of \(\oplus\) or \(\otimes\) is also a division. This means we
only need the groupings</p>

<p>\[(x_0 \odot x_1) \oplus (x_2 \otimes x_3)\]\[((x_0 \odot x_1) \oplus x_2) \otimes x_3\]\[(x_0 \odot (x_1 \oplus x_2)) \otimes x_3\]</p>

<p>to find all possible solutions. Our solution becomes:</p>
<div class="highlight"><pre><span/><span class="kn">from</span><span class="w"> </span><span class="nn">itertools</span><span class="w"> </span><span class="kn">import</span> <span class="n">permutations</span><span class="p">,</span> <span class="n">product</span>
<span class="kn">from</span><span class="w"> </span><span class="nn">sys</span><span class="w"> </span><span class="kn">import</span> <span class="n">argv</span>

<span class="n">args</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">11</span><span class="p">]</span> <span class="k">if</span> <span class="n">arg</span> <span class="ow">in</span> <span class="s1">'aA'</span> <span class="k">else</span>
    <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">arg</span><span class="p">)]</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">5</span><span class="p">]],</span> <span class="p">[])</span>

<span class="k">for</span> <span class="n">xs</span> <span class="ow">in</span> <span class="n">permutations</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="mi">4</span><span class="p">):</span>
    <span class="k">if</span> <span class="nb">sum</span><span class="p">(</span><span class="n">n</span> <span class="o">==</span> <span class="mi">1</span> <span class="ow">or</span> <span class="n">n</span> <span class="o">==</span> <span class="mi">11</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">xs</span><span class="p">)</span> <span class="o">&gt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span> <span class="o">-</span> <span class="mi">4</span><span class="p">:</span>
        <span class="k">continue</span>

    <span class="k">for</span> <span class="n">ops</span> <span class="ow">in</span> <span class="n">product</span><span class="p">(</span><span class="s1">'+-*/'</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="mi">3</span><span class="p">):</span>
        <span class="k">for</span> <span class="n">exp</span> <span class="ow">in</span> <span class="p">[</span><span class="s1">'(</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> (</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">)'</span><span class="p">,</span>
                    <span class="s1">'((</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">'</span><span class="p">,</span>
                    <span class="s1">'(</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> (</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">)) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">'</span><span class="p">]:</span>

            <span class="n">exp</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">xs</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">ops</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">xs</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">ops</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">xs</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span>
                <span class="n">ops</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">xs</span><span class="p">[</span><span class="mi">3</span><span class="p">])</span>

            <span class="k">try</span><span class="p">:</span>
                <span class="k">if</span> <span class="nb">eval</span><span class="p">(</span><span class="n">exp</span><span class="p">)</span> <span class="o">==</span> <span class="mi">24</span><span class="p">:</span>
                    <span class="nb">print</span><span class="p">(</span><span class="n">exp</span><span class="p">)</span>
                    <span class="n">exit</span><span class="p">()</span>
            <span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
                <span class="k">pass</span>

<span class="nb">print</span><span class="p">(</span><span class="s1">'No solution'</span><span class="p">)</span>
</pre></div>

<p>This means that for games without aces, we need to check 24 (\(4!\))
permutations of cards, 64 (\(4^3\)) combinations of operators, and 3
groupings. That is \(4! * 4^3 * 3 = 4608\) tests. For games with aces, we
double this number for each ace to account for both the 1 and 11 cases.</p>

<h2>Minimizing Number of Tests</h2>

<p>A more interesting question is what is the minimum number of tests we
need to perform in order to correctly find a solution for all solvable
games.</p>

<p>It is obvious that there are expressions which can never evaluate to 24
for any game. For example \((x_0 - x_1) - x_2) - x_3\), since
\(x_i \in \{1,
2, ... 11\}\).</p>

<p>It is also obvious that we perform a lot of redundant tests, since, for
example, all of the below expressions are equivalent for all possible
inputs:</p>

<p>\[(x_0 + x_1) + (x_2 + x_3)\]\[((x_0 + x_1) + x_2) + x_3\]\[(x_0 + (x_1 + x_2)) + x_3\]\[(x_0 + x_1) + (x_3 + x_2)\]\[((x_0 + x_1) + x_3) + x_2\]\[(x_0 + (x_1 + x_3)) + x_2\]\[...\]</p>

<p>and so on for all permutations of \(x_0, x_1, x_2, x_3\).</p>

<p>Let's generate all possible permutations of cards, combinations of
operators, and groupings as above:</p>
<div class="highlight"><pre><span/><span class="kn">import</span><span class="w"> </span><span class="nn">itertools</span>

<span class="n">operands</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">permutations</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">),</span> <span class="mi">4</span><span class="p">))</span> <span class="c1"># 24 of these</span>
<span class="n">operators</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">product</span><span class="p">(</span><span class="s1">'+-*/'</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="mi">3</span><span class="p">))</span> <span class="c1"># 64 of these</span>
<span class="n">groupings</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'(</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> (</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">)'</span><span class="p">,</span>
             <span class="s1">'((</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">'</span><span class="p">,</span>
             <span class="s1">'(</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> (</span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">)) </span><span class="si">{}</span><span class="s1"> </span><span class="si">{}</span><span class="s1">'</span><span class="p">]</span> <span class="c1"># 3 of these</span>
</pre></div>

<p>Note that here we are looking at all possible games so operands are
permutations of indexes from 0 to 3, not actual cards. We can also take
all possible games as combinations of 4 numbers from 1 to 11. Here we
generate 1 and 11 games for each ace, so we end up with 1001 possible
games instead of 715:</p>
<div class="highlight"><pre><span/><span class="n">inputs</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="o">.</span><span class="n">combinations_with_replacement</span><span class="p">(</span><span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">12</span><span class="p">),</span> <span class="mi">4</span><span class="p">))</span>
<span class="c1">## 1001 of these</span>
</pre></div>

<p>We can now write a function that, for a given game, generates all
possible expressions which evaluate to 24:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">solutions_for</span><span class="p">(</span><span class="n">inp</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">xs</span> <span class="ow">in</span> <span class="n">operands</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">ops</span> <span class="ow">in</span> <span class="n">operators</span><span class="p">:</span>
            <span class="k">for</span> <span class="n">exp</span> <span class="ow">in</span> <span class="n">groupings</span><span class="p">:</span>
                <span class="k">try</span><span class="p">:</span>
                    <span class="k">if</span> <span class="nb">eval</span><span class="p">(</span><span class="n">exp</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">inp</span><span class="p">[</span><span class="n">xs</span><span class="p">[</span><span class="mi">0</span><span class="p">]],</span> <span class="n">ops</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
                            <span class="n">inp</span><span class="p">[</span><span class="n">xs</span><span class="p">[</span><span class="mi">1</span><span class="p">]],</span> <span class="n">ops</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="n">inp</span><span class="p">[</span><span class="n">xs</span><span class="p">[</span><span class="mi">2</span><span class="p">]],</span>
                            <span class="n">ops</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="n">inp</span><span class="p">[</span><span class="n">xs</span><span class="p">[</span><span class="mi">3</span><span class="p">]]))</span> <span class="o">==</span> <span class="mi">24</span><span class="p">:</span>
                        <span class="k">yield</span> <span class="n">exp</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="sa">f</span><span class="s1">'x</span><span class="si">{</span><span class="n">xs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span> <span class="n">ops</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span>
                            <span class="sa">f</span><span class="s1">'x</span><span class="si">{</span><span class="n">xs</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span> <span class="n">ops</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="sa">f</span><span class="s1">'x</span><span class="si">{</span><span class="n">xs</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="si">}</span><span class="s1">'</span><span class="p">,</span>
                            <span class="n">ops</span><span class="p">[</span><span class="mi">2</span><span class="p">],</span> <span class="sa">f</span><span class="s1">'x</span><span class="si">{</span><span class="n">xs</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span><span class="si">}</span><span class="s1">'</span><span class="p">)</span>
                <span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
                    <span class="k">pass</span>
</pre></div>

<p>This is very similar with the initial solution, except that we don't
have to worry about aces (we assume they are already converted to either
1 or 11), and we use the permutations of indexes to determine the order
of terms as input is going to always be in increasing order (as
generated by <code>itertools.combinations_with_replacement</code>). So instead of
placing <code>inp[0], op[0], inp[1], op[1], inp[2], op[2], inp[3]</code> in the
expression to be evaluated as we did in the initial solution, since
<code>inp</code> is fixed, we come up with permutations of operands from
<code>operands</code>, so we are placing
<code>inp[xs[0]], op[0], inp[xs[1]], op[1], inp[xs[2]], op[2], inp[xs[3]]</code> in
the expression instead. We also return the expression replacing the
operands with <code>x0, x1, x2, x3</code> since we don't care about their
particular values, rather the expression we are using.</p>

<p>For example calling:</p>
<div class="highlight"><pre><span/><span class="nb">list</span><span class="p">(</span><span class="n">solutions_for</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">]))</span>
</pre></div>

<p>yields</p>
<div class="highlight"><pre><span/>['((x0 * x2) - x3) * x1', '(x1 * x2) - (x3 / x0)',
 '((x2 * x0) - x3) * x1', '((x2 / x0) * x3) - x1',
 '(x2 / (x0 / x3)) - x1', '(x2 * x1) - (x3 / x0)',
 '((x2 * x3) / x0) - x1', '(x2 * (x3 / x0)) - x1',
 '((x3 / x0) * x2) - x1', '(x3 / (x0 / x2)) - x1',
 '((x3 * x2) / x0) - x1', '(x3 * (x2 / x0)) - x1']
</pre></div>

<p>These are all possible expression which evaluate to 24 for the game
<code>2 4 7 8</code>.</p>

<p>We can compute the list of all expressions which evaluate to 24 for
every possible game:</p>
<div class="highlight"><pre><span/><span class="n">results</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">inp</span> <span class="ow">in</span> <span class="n">inputs</span><span class="p">:</span>
    <span class="n">result</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">solutions_for</span><span class="p">(</span><span class="n">inp</span><span class="p">))</span>

    <span class="c1"># Only append the set of expressions to the list if</span>
    <span class="c1"># non-empty (if game has at least one solution)</span>
    <span class="k">if</span> <span class="n">result</span><span class="p">:</span>
        <span class="n">results</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
</pre></div>

<p>We can take the union of the sets in <code>results</code> and get the set of all
expressions that evaluate to 24 for at least one game:</p>
<div class="highlight"><pre><span/><span class="n">expressions</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
    <span class="n">expressions</span> <span class="o">=</span> <span class="n">expressions</span><span class="o">.</span><span class="n">union</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
</pre></div>

<p>The size of this set is 1809. We are guaranteed that for any possible
game, no other expression evaluates to 24 since we generated all
possible solutions for all possible games. Which means we can test just
these 1809 expression for any game and determine whether it is solvable
or not, which is better than our original 4608 (or more for games with
aces).</p>

<p>Here we eliminated all expressions which never evaluate to 24, but we
still have all the redundant tests in our set of expressions. It is also
possible to have an expression \(E_0\) which solves all games some
expression \(E_1\) solves, plus some other games. In which case we
wouldn't ever need to test using \(E_1\) since \(E_0\) would still solve
all games that \(E_1\) would solve.</p>

<p>More formally, <code>expressions</code> is our universe \(\mathcal{U}\) of tests and
<code>results</code> is a set of sets \(R = \{ R_0, R_1 ... R_n \}\) where
\(R_i \subset \mathcal{U} \space \forall i \in \{ 0, 1 ... n \}\). We want
to find the smallest set \(H \subset \mathcal{U}\) such that \(H \cap
R_i \neq \varnothing \space \forall i \in \{ 0, 1 ... n \}\).</p>

<p>The good news is that this is actually a well known problem called <strong>the
hitting set problem</strong><sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. The bad news is this problem is NP-hard. Even
with clever pruning, trying out combinations of expressions to find the
smallest \(H\) has factorial complexity and even for small sets it quickly
reaches astronomical numbers.</p>

<h2>Approximation</h2>

<p>Since finding an optimal solution is too computationally expensive, we
can at least attempt to find a <em>good enough</em> solution.</p>

<p>The greedy algorithm which solves the hitting set problem works as
follows: build up the solution by selecting at each step the element
which hits the highest number of sets which were not hit so far.</p>
<div class="highlight"><pre><span/><span class="c1">## Start with an empty set</span>
<span class="n">min_expressions</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>

<span class="c1">## While we have unhit sets</span>
<span class="k">while</span> <span class="n">results</span><span class="p">:</span>
    <span class="n">min_expression</span><span class="p">,</span> <span class="n">max_hitting</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(),</span> <span class="mi">0</span>

    <span class="c1"># For each expression in our universe</span>
    <span class="k">for</span> <span class="n">expr</span> <span class="ow">in</span> <span class="n">expressions</span><span class="p">:</span>
        <span class="n">hitting</span> <span class="o">=</span> <span class="nb">sum</span><span class="p">([</span><span class="mi">1</span> <span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">results</span> <span class="k">if</span> <span class="n">expr</span> <span class="ow">in</span> <span class="n">result</span><span class="p">])</span>
        <span class="k">if</span> <span class="n">hitting</span> <span class="o">&gt;</span> <span class="n">max_hitting</span><span class="p">:</span>
            <span class="n">min_expression</span><span class="p">,</span> <span class="n">max_hitting</span> <span class="o">=</span> <span class="n">expr</span><span class="p">,</span> <span class="n">hitting</span>

    <span class="c1"># We found the expression hitting most unhit sets</span>
    <span class="n">min_expressions</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">min_expression</span><span class="p">)</span>

    <span class="c1"># Remove hit sets from results</span>
    <span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="n">result</span> <span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">results</span> <span class="k">if</span>
        <span class="n">min_expression</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">result</span><span class="p">]</span>
</pre></div>

<p>Interestingly enough, since we are working with sets and hashing is
randomized in Python, I got different results across different runs of
this algorithm. For cases where there are multiple max hitting sets
(sets intersecting the same number of other sets), we
non-deterministically select one, since iteration over sets is based on
the randomized key order. I got solutions ranging from 110 to 114
expressions. This gives us an upper bound of 110 - we must perform at
most 110 tests to find a solution for a game.</p>

<p>We can use the above code to generate a set of expressions and dump it
into a source file, together with the code to test input:</p>
<div class="highlight"><pre><span/><span class="kn">from</span><span class="w"> </span><span class="nn">sys</span><span class="w"> </span><span class="kn">import</span> <span class="n">argv</span>

<span class="n">expressions</span> <span class="o">=</span> <span class="p">[</span>
    <span class="s2">"(x3 + x1) * (x2 - x0)"</span><span class="p">,</span> <span class="s2">"((x2 * x3) - x0) / x1"</span><span class="p">,</span>
    <span class="s2">"(x3 + (x1 + x0)) * x2"</span><span class="p">,</span> <span class="s2">"(x0 - x3) * (x1 - x2)"</span><span class="p">,</span>
    <span class="s2">"(x1 * x0) + (x2 - x3)"</span><span class="p">,</span> <span class="s2">"((x2 * x0) * x3) - x1"</span><span class="p">,</span>
    <span class="s2">"(x3 + (x1 + x2)) + x0"</span><span class="p">,</span> <span class="s2">"(x2 * x0) + (x3 - x1)"</span><span class="p">,</span>
    <span class="s2">"((x0 / x1) * x2) * x3"</span><span class="p">,</span> <span class="s2">"(x1 * (x3 - x2)) + x0"</span><span class="p">,</span>
    <span class="s2">"((x3 + x2) - x0) + x1"</span><span class="p">,</span> <span class="s2">"(x0 * x1) * (x3 - x2)"</span><span class="p">,</span>
    <span class="s2">"(x1 * x0) - (x2 + x3)"</span><span class="p">,</span> <span class="s2">"(x3 / x1) * (x2 + x0)"</span><span class="p">,</span>
    <span class="s2">"((x2 + x1) + x3) * x0"</span><span class="p">,</span> <span class="s2">"(x3 - x0) / (x1 / x2)"</span><span class="p">,</span>
    <span class="s2">"(x3 + x1) * (x2 / x0)"</span><span class="p">,</span> <span class="s2">"(x1 * x3) + (x0 * x2)"</span><span class="p">,</span>
    <span class="s2">"((x3 * x1) + x2) + x0"</span><span class="p">,</span> <span class="s2">"((x0 - x2) + x1) * x3"</span><span class="p">,</span>
    <span class="s2">"((x3 / x0) + x2) * x1"</span><span class="p">,</span> <span class="s2">"(x3 + (x2 * x1)) - x0"</span><span class="p">,</span>
    <span class="s2">"(x1 * x3) - (x2 - x0)"</span><span class="p">,</span> <span class="s2">"(x1 * (x3 - x0)) - x2"</span><span class="p">,</span>
    <span class="s2">"((x2 + x1) * x3) / x0"</span><span class="p">,</span> <span class="s2">"(x0 * x3) - (x1 + x2)"</span><span class="p">,</span>
    <span class="s2">"(x1 + (x3 * x0)) * x2"</span><span class="p">,</span> <span class="s2">"(x0 * (x2 + x3)) - x1"</span><span class="p">,</span>
    <span class="s2">"(x1 * x3) - (x0 + x2)"</span><span class="p">,</span> <span class="s2">"(x3 - (x2 / x1)) * x0"</span><span class="p">,</span>
    <span class="s2">"(x0 - (x1 / x2)) * x3"</span><span class="p">,</span> <span class="s2">"(x3 * x0) + (x2 - x1)"</span><span class="p">,</span>
    <span class="s2">"((x3 / x0) + x1) + x2"</span><span class="p">,</span> <span class="s2">"(x3 + (x1 * x2)) + x0"</span><span class="p">,</span>
    <span class="s2">"(x0 + x2) * (x1 + x3)"</span><span class="p">,</span> <span class="s2">"(x0 * (x3 - x1)) + x2"</span><span class="p">,</span>
    <span class="s2">"((x0 + x3) * x1) * x2"</span><span class="p">,</span> <span class="s2">"(x2 * (x0 + x3)) / x1"</span><span class="p">,</span>
    <span class="s2">"(x2 - (x1 + x0)) * x3"</span><span class="p">,</span> <span class="s2">"(x3 * x2) - (x0 / x1)"</span><span class="p">,</span>
    <span class="s2">"((x0 + x3) * x1) + x2"</span><span class="p">,</span> <span class="s2">"((x0 * x3) + x1) - x2"</span><span class="p">,</span>
    <span class="s2">"(x2 + (x3 - x1)) * x0"</span><span class="p">,</span> <span class="s2">"(x2 * (x0 + x1)) + x3"</span><span class="p">,</span>
    <span class="s2">"((x2 + x3) * x0) + x1"</span><span class="p">,</span> <span class="s2">"(x0 - (x3 / x2)) * x1"</span><span class="p">,</span>
    <span class="s2">"((x0 + x2) - x3) * x1"</span><span class="p">,</span> <span class="s2">"((x3 / x2) + x0) * x1"</span><span class="p">,</span>
    <span class="s2">"(x1 / x0) + (x2 + x3)"</span><span class="p">,</span> <span class="s2">"((x1 * x0) - x2) * x3"</span><span class="p">,</span>
    <span class="s2">"((x0 + x1) + x2) * x3"</span><span class="p">,</span> <span class="s2">"(x2 * (x3 - x1)) - x0"</span><span class="p">,</span>
    <span class="s2">"((x2 * x1) - x0) * x3"</span><span class="p">,</span> <span class="s2">"((x3 - x1) * x2) + x0"</span><span class="p">,</span>
    <span class="s2">"(x3 / (x0 + x1)) * x2"</span><span class="p">,</span> <span class="s2">"((x1 * x0) + x3) + x2"</span><span class="p">,</span>
    <span class="s2">"(x3 + x0) * (x2 - x1)"</span><span class="p">,</span> <span class="s2">"(x2 - x0) * (x3 - x1)"</span><span class="p">,</span>
    <span class="s2">"((x3 / x0) * x2) + x1"</span><span class="p">,</span> <span class="s2">"((x2 * x1) - x0) - x3"</span><span class="p">,</span>
    <span class="s2">"(x0 + (x3 - x1)) * x2"</span><span class="p">,</span> <span class="s2">"(x0 * x2) / (x3 - x1)"</span><span class="p">,</span>
    <span class="s2">"((x3 * x2) - x1) / x0"</span><span class="p">,</span> <span class="s2">"(x2 - (x0 / x3)) * x1"</span><span class="p">,</span>
    <span class="s2">"(x3 - x2) * (x0 + x1)"</span><span class="p">,</span> <span class="s2">"(x0 * x2) - (x3 + x1)"</span><span class="p">,</span>
    <span class="s2">"((x2 - x0) * x3) + x1"</span><span class="p">,</span> <span class="s2">"(x1 * (x3 - x0)) + x2"</span><span class="p">,</span>
    <span class="s2">"(x1 * (x0 + x3)) - x2"</span><span class="p">,</span> <span class="s2">"((x0 + x1) * x3) + x2"</span><span class="p">,</span>
    <span class="s2">"((x1 - x2) + x3) * x0"</span><span class="p">,</span> <span class="s2">"((x3 - x1) * x2) * x0"</span><span class="p">,</span>
    <span class="s2">"((x2 + x1) - x3) * x0"</span><span class="p">,</span> <span class="s2">"(x1 + (x3 / x2)) * x0"</span><span class="p">,</span>
    <span class="s2">"(x2 / (x0 / x1)) + x3"</span><span class="p">,</span> <span class="s2">"(x2 / (x3 - x0)) * x1"</span><span class="p">,</span>
    <span class="s2">"(x3 * x1) - (x0 * x2)"</span><span class="p">,</span> <span class="s2">"((x1 + x0) * x2) * x3"</span><span class="p">,</span>
    <span class="s2">"(x1 - (x2 / x3)) * x0"</span><span class="p">,</span> <span class="s2">"(x2 + (x3 * x0)) + x1"</span><span class="p">,</span>
    <span class="s2">"((x2 * x3) + x1) / x0"</span><span class="p">,</span> <span class="s2">"(x3 - x0) * (x2 + x1)"</span><span class="p">,</span>
    <span class="s2">"(x1 * x3) + (x2 - x0)"</span><span class="p">,</span> <span class="s2">"(x3 * (x2 - x0)) - x1"</span><span class="p">,</span>
    <span class="s2">"(x0 + (x1 - x3)) * x2"</span><span class="p">,</span> <span class="s2">"(x1 * (x3 - x2)) - x0"</span><span class="p">,</span>
    <span class="s2">"(x0 + (x2 * x3)) - x1"</span><span class="p">,</span> <span class="s2">"(x2 + x3) / (x0 / x1)"</span><span class="p">,</span>
    <span class="s2">"(x0 * x3) / (x2 - x1)"</span><span class="p">,</span> <span class="s2">"(x2 - (x3 / x0)) * x1"</span><span class="p">,</span>
    <span class="s2">"(x0 - (x1 - x2)) * x3"</span><span class="p">,</span> <span class="s2">"(x3 + x1) + (x2 * x0)"</span><span class="p">,</span>
    <span class="s2">"((x3 - x1) - x0) * x2"</span><span class="p">,</span> <span class="s2">"(x1 * (x2 - x0)) - x3"</span><span class="p">,</span>
    <span class="s2">"(x2 + x0) * (x3 - x1)"</span><span class="p">,</span> <span class="s2">"((x3 - x1) * x2) / x0"</span><span class="p">,</span>
    <span class="s2">"((x1 * x3) - x2) * x0"</span><span class="p">,</span> <span class="s2">"((x1 + x3) * x0) - x2"</span><span class="p">,</span>
    <span class="s2">"((x3 - x2) + x0) * x1"</span><span class="p">,</span> <span class="s2">"((x2 * x0) - x3) * x1"</span><span class="p">,</span>
    <span class="s2">"(x2 * (x1 + x0)) - x3"</span><span class="p">,</span> <span class="s2">"(x0 + (x1 / x2)) * x3"</span><span class="p">,</span>
    <span class="s2">"((x2 - x1) * x3) + x0"</span><span class="p">,</span> <span class="s2">"((x2 / x1) + x3) * x0"</span><span class="p">,</span>
    <span class="s2">"(x1 * x0) - (x2 / x3)"</span><span class="p">,</span> <span class="s2">"((x3 * x0) - x1) * x2"</span><span class="p">,</span>
    <span class="s2">"((x2 - x0) * x1) + x3"</span><span class="p">,</span> <span class="s2">"((x1 + x0) * x3) - x2"</span><span class="p">,</span>
    <span class="s2">"(x1 * x0) / (x3 - x2)"</span><span class="p">,</span> <span class="s2">"(x3 * (x1 - x0)) - x2"</span>
<span class="p">]</span>

<span class="c1">## Since we no longer try all permutations of cards, we</span>
<span class="c1">## need to split inputs containing aces by replacing aces</span>
<span class="c1">## with both 1 and 11</span>
<span class="k">def</span><span class="w"> </span><span class="nf">get_input</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
    <span class="k">if</span> <span class="s1">'A'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
        <span class="k">return</span> <span class="p">[</span><span class="n">args</span><span class="p">]</span>

    <span class="n">idx</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">index</span><span class="p">(</span><span class="s1">'A'</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">get_input</span><span class="p">(</span><span class="n">args</span><span class="p">[:</span><span class="n">idx</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="s1">'1'</span><span class="p">]</span> <span class="o">+</span> <span class="n">args</span><span class="p">[</span><span class="n">idx</span><span class="o">+</span><span class="mi">1</span><span class="p">:]</span>
        <span class="p">)</span> <span class="o">+</span> <span class="n">get_input</span><span class="p">(</span><span class="n">args</span><span class="p">[:</span><span class="n">idx</span><span class="p">]</span> <span class="o">+</span> <span class="p">[</span><span class="s1">'11'</span><span class="p">]</span> <span class="o">+</span> <span class="n">args</span><span class="p">[</span><span class="n">idx</span><span class="o">+</span><span class="mi">1</span><span class="p">:])</span>

<span class="k">for</span> <span class="n">args</span> <span class="ow">in</span> <span class="n">get_input</span><span class="p">(</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">5</span><span class="p">]):</span>
    <span class="c1"># We also expect inputs to be in sorted order now</span>
    <span class="n">args</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">([</span><span class="nb">int</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span> <span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">])</span>

    <span class="k">for</span> <span class="n">exp</span> <span class="ow">in</span> <span class="n">expressions</span><span class="p">:</span>
        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4</span><span class="p">):</span>
            <span class="c1"># Replace x0 ... x3 with args[0] ... args[3]</span>
            <span class="n">exp</span> <span class="o">=</span> <span class="n">exp</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s1">'x'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">),</span> <span class="nb">str</span><span class="p">(</span><span class="n">args</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="k">if</span> <span class="nb">eval</span><span class="p">(</span><span class="n">exp</span><span class="p">)</span> <span class="o">==</span> <span class="mi">24</span><span class="p">:</span>
                <span class="nb">print</span><span class="p">(</span><span class="n">exp</span><span class="p">)</span>
                <span class="k">return</span>
        <span class="k">except</span> <span class="ne">ZeroDivisionError</span><span class="p">:</span>
            <span class="k">pass</span>

<span class="nb">print</span><span class="p">(</span><span class="s1">'No solution'</span><span class="p">)</span>
</pre></div>

<p>We can test this by ensuring that we still see 117 games without
solution when we try to solve all 715 games, which is indeed the case.
We reduced the number of tests we perform on a game from 4608 to 110.</p>

<h2>Unique Expressions</h2>

<p>There are a couple of other interesting facts we can determine from the
set of all solutions for all games: the set of unique expressions and
out of them, the subset of expressions which are absolutely required in
order to solve all possible games.</p>

<p>By <em>unique expression</em> I mean picking an expression and eliminating all
other equivalent expressions from the set (for example keeping only
\(((x_0 + x_1) + x_2) + x_3\) while dropping all other permutations and
groupings of addition). We can easily do this by defining equivalent
expressions as expressions which solve the exact same games. So if \(E_1\)
solves some subset \(R_{E_1}\) of \(R\), an expression \(E_2\) is equivalent
to it if the set \(R_{E_2}\) of games it solves is equal to \(R_{E_1}\). We
can define equivalence as:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">equivalent</span><span class="p">(</span><span class="n">exp1</span><span class="p">,</span> <span class="n">exp2</span><span class="p">):</span>
    <span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
        <span class="k">if</span> <span class="n">exp1</span> <span class="ow">in</span> <span class="n">result</span> <span class="ow">and</span> <span class="n">exp2</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">False</span>
        <span class="k">if</span> <span class="n">exp1</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">result</span> <span class="ow">and</span> <span class="n">exp2</span> <span class="ow">in</span> <span class="n">result</span><span class="p">:</span>
            <span class="k">return</span> <span class="kc">False</span>
    <span class="k">return</span> <span class="kc">True</span>
</pre></div>

<p>With this function, we can go over our univese \(\mathcal{U}\) of
expressions and eliminate all expressions which are the equivalent of
another expression:</p>
<div class="highlight"><pre><span/><span class="n">expressions</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">expressions</span><span class="p">)</span>
<span class="n">i1</span><span class="p">,</span> <span class="n">i2</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">i1</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">expressions</span><span class="p">):</span>
    <span class="n">i2</span> <span class="o">=</span> <span class="n">i1</span> <span class="o">+</span> <span class="mi">1</span>
    <span class="k">while</span> <span class="n">i2</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">expressions</span><span class="p">):</span>
        <span class="k">if</span> <span class="n">equivalent</span><span class="p">(</span><span class="n">expressions</span><span class="p">[</span><span class="n">i1</span><span class="p">],</span> <span class="n">expressions</span><span class="p">[</span><span class="n">i2</span><span class="p">]):</span>
            <span class="n">expressions</span> <span class="o">=</span> <span class="n">expressions</span><span class="p">[:</span><span class="n">i2</span><span class="p">]</span> <span class="o">+</span> <span class="n">expressions</span><span class="p">[</span><span class="n">i2</span><span class="o">+</span><span class="mi">1</span><span class="p">:]</span>
        <span class="k">else</span><span class="p">:</span>
            <span class="n">i2</span> <span class="o">+=</span> <span class="mi">1</span>
    <span class="n">i1</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">expressions</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">expressions</span><span class="p">)</span>
</pre></div>

<p>The resulting set of unique expressions has 273 elements. This means
these 273 expressions are enough to solve all possible games and, more
so, adding any other expression to this set would be redundant. This is
a lower bound than our original 1809 expressions which solve games, but
higher than our previously found bound of 110 expressions. Note that
this data point is not useful in the greedy algorithm shown in the
previous section, since once that algorithm picks an expression, it
would automatically discard all other equivalent expressions, since it
eliminates all games which are solved by the picked expression from the
search space. This should put the problem in combinatorial perspective
though, as we need to select from 273 candidates to find the smallest
hitting set.</p>

<p>Once we have eliminated equivalent expressions, we can update the set of
game results accordingly, by intersecting each \(R_i\) with our new
\(\mathcal{U}\):</p>
<div class="highlight"><pre><span/><span class="n">results</span> <span class="o">=</span> <span class="p">[</span><span class="nb">list</span><span class="p">(</span><span class="n">expressions</span><span class="o">.</span><span class="n">intersection</span><span class="p">(</span><span class="n">result</span><span class="p">))</span> <span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">results</span><span class="p">]</span>
</pre></div>

<p>Now we can search \(R\) for sets with a single element. This will give us
expressions which must be part of our solution, otherwise eliminating
them would cause a solvable game to appear as unsolvable:</p>
<div class="highlight"><pre><span/><span class="n">min_expressions</span><span class="p">,</span> <span class="n">games_with_unique_result</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(),</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">result</span> <span class="ow">in</span> <span class="n">results</span><span class="p">:</span>
    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
        <span class="n">min_expressions</span> <span class="o">=</span> <span class="n">min_expressions</span><span class="o">.</span><span class="n">union</span><span class="p">(</span><span class="n">result</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
        <span class="n">games_with_unique_result</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>

<p>Turns out there are 62 expressions which (ignoring equivalences) provide
unique solutions to games. They are:</p>
<div class="highlight"><pre><span/>{'(x1 + x2) - (x0 - x3)', '(x1 + x0) * (x2 * x3)',
 '((x1 + x0) - x2) * x3', '((x3 + x2) * x0) + x1',
 '(x0 + x3) * (x2 - x1)', '((x2 * x1) / x0) + x3',
 '((x3 - x1) * x2) - x0', '(x1 - (x3 / x2)) * x0',
 '((x1 * x0) - x2) - x3', '((x2 - x1) - x0) * x3',
 '((x1 * x0) - x3) + x2', '(x2 + (x1 / x0)) + x3',
 '((x1 + x3) - x2) * x0', '(x2 - (x3 - x0)) * x1',
 '(x2 + (x1 + x3)) + x0', '(x1 * x0) - (x2 / x3)',
 '(x3 + (x2 * x1)) - x0', '((x0 * x1) + x3) + x2',
 '(x2 + (x1 - x3)) * x0', '((x0 * x1) - x2) * x3',
 '(x2 * x0) + (x1 + x3)', '(x2 + (x3 * x0)) + x1',
 '((x0 * x3) - x1) + x2', '(x0 + (x2 - x1)) * x3',
 '((x3 * x1) - x2) - x0', '(x1 - x2) * (x0 - x3)',
 '((x3 - x0) - x1) * x2', '(x1 * (x2 - x0)) - x3',
 '(x0 / (x3 - x2)) * x1', '((x0 + x1) - x3) * x2',
 '((x3 - x1) + x0) * x2', '((x1 + x0) * x3) + x2',
 '((x1 + x0) * x3) - x2', '(x3 / x1) * (x2 + x0)',
 '((x3 - x1) * x0) + x2', '(x3 * (x2 - x0)) + x1',
 '((x0 + x2) + x1) * x3', '(x2 * (x0 + x1)) - x3',
 '(x2 * x1) / (x3 - x0)', '(x3 + x0) + (x1 * x2)',
 '(x0 + (x3 * x2)) - x1', '(x0 - x2) * (x1 - x3)',
 '((x2 + x3) * x1) / x0', '(x2 / x0) * (x3 + x1)',
 '(x3 * (x1 - x0)) - x2', '((x3 + x1) * x0) - x2',
 '((x0 + x3) * x1) - x2', '((x3 + x2) * x0) - x1',
 '(x3 + x0) / (x1 / x2)', '(x0 + x2) * (x3 - x1)',
 '(x2 * (x3 - x1)) + x0', '((x0 * x3) - x2) - x1',
 '((x1 * x2) - x3) - x0', '(x3 - (x1 - x2)) * x0',
 '(x2 * x3) / (x1 + x0)', '(x3 - x2) * (x0 + x1)',
 '(x0 / (x3 - x1)) * x2', '((x2 * x3) - x0) / x1',
 '(x2 * (x3 - x0)) / x1', '((x1 + x0) * x2) + x3',
 '(x1 * (x2 - x0)) + x3', '(x3 * (x2 - x1)) + x0'}
</pre></div>

<p>This is a lower bound for our problem, since at the very least we need
these expressions in order to correcly solve all possible games. We also
computed the number of games with a unique solution, which is 122. The
remaining games are either unsolvable or admit multiple solutions. Note
we considered aces as 1s and aces as 11s as distinct games in the above
analysis. We could search for equivalent games (number of 1s and 11s is
the same) and see if we can eliminate some expressions from the list
above. This is left as an exercise to the reader.</p>

<h2>Summary</h2>

<ul>
<li>There are 715 distinct games in 24, with 117 of them unsolvable and
the remaining 598 having at least one solution.</li>
<li>A brute-force solution checks 4608 expressions (double for each ace)
to determine that a game is unsolvable.</li>
<li>Only 1809 expressions (out of the 4608) solve at least one game.</li>
<li>Finding the minimum number of expressions we need to check in order
to find whether a game has a solution is equivalent to the hitting
set problem which is NP-hard.</li>
<li>A greedy algorithm finds a set of 110 expressions which is enough to
find a solution for any solvable game.</li>
<li>Removing equivalent expressions, we are left with 273 expressions
which all solve at least one different game than any other. Out of
these, 62 expressions are unique solutions to 122 games, so they
must necessarily be checked in order to find solutions for all
possible games.</li>
</ul>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>Wikipedia explains the <a href="https://en.wikipedia.org/wiki/Set_cover_problem">set cover
problem</a> which is
equivalent to the hitting set problem (one can be converted to the
other). <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sun, 13 Aug 2017 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/07/20/idris-totality-dependent-types-proofs.html</link>
      <guid>https://vladris.com/blog/2017/07/20/idris-totality-dependent-types-proofs.html</guid>
      <title><![CDATA[Idris: Totality, Dependent Types, Proofs]]></title>
      <description><![CDATA[<h1>Idris: Totality, Dependent Types, Proofs</h1>

<p>Idris is a programming language inspired by Haskell, with a set of
innovative features to facilitate type safety and program correctness.
<a href="https://www.manning.com/books/type-driven-development-with-idris">Type Driven Development with
Idris</a>
is a great introductory book which I highly recommend. In this post, I
will try to cover the features I was most impressed with, providing some
simple code samples. I will not cover syntax since most should be
familiar from Haskell. If you are not familiar with Haskell syntax, here
is a nice <a href="https://matela.com.br/pub/cheat-sheets/haskell-ucs-0.4.pdf">syntax cheat
sheet</a>. If
you are not interested in either Haskell or Idris syntax, start with the
last section of this post, <a href="#thoughts-about-the-future">Thoughts about the
Future</a>.</p>

<h2>Totality Checking</h2>

<p>A total function in Idris is a function which is defined for all
possible inputs and is guaranteed to produce a result in a finite amount
of time<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. The compiler obviously employs a heuristic, since the
halting problem is undecidable, but is usually close enough to the truth
to guarantee correctness from this point of view. It achieves this not
by evaluating the function, but by ensuring that every recursive branch
converges to a halting branch.</p>

<p>Natural numbers are defined in Idris using Peano axioms, so it is easy
to prove things about them. Here is a minimal definition of natural
numbers<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>:</p>
<div class="highlight"><pre><span/><span class="kr">data</span><span class="w"> </span><span class="kt">Nat'</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Z</span><span class="w"> </span><span class="ow">|</span><span class="w"> </span><span class="kt">S</span><span class="w"> </span><span class="kt">Nat'</span>
</pre></div>

<p>This defines <code>Nat'</code> as a data type which can be constructed either as
<code>Z</code> (zero) or <code>S Nat'</code> (successor of another natural number). With this
definition, the compiler can easily determine the following function is
total:</p>
<div class="highlight"><pre><span/><span class="nf">f</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Nat'</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="ow">()</span>
f<span class="w"> </span><span class="kt">Z</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="ow">()</span>
f<span class="w"> </span><span class="ow">(</span><span class="kt">S</span><span class="w"> </span>k<span class="ow">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span>f<span class="w"> </span>k
</pre></div>

<p>This function return a unit given <code>Z</code>, otherwise it recursively takes
the predecessor of the argument. This converges to the <code>Z</code> case. The
following function, on the other hand, is correctly identified as
potentially non-terminating:</p>
<div class="highlight"><pre><span/><span class="nf">g</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Nat'</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="ow">()</span>
g<span class="w"> </span>n<span class="w"> </span><span class="ow">=</span><span class="w"> </span>g<span class="w"> </span><span class="ow">(</span><span class="kt">S</span><span class="w"> </span>n<span class="ow">)</span>
</pre></div>

<p>These are trivial examples, but in general, having a compile-time check
for termination is a very powerful tool.</p>

<h2>Dependent Types</h2>

<p>Dependent types are types computed from other types. To put it another
way, Idris has first-order types, meaning functions can take types as
arguments and return types as their output. Functions that compute types
are evaluated at compile time. This is similar to C++ metaprogramming,
but without employing a different syntax.</p>

<p>Before an example, we first need to define addition on naturals as
follows:</p>
<div class="highlight"><pre><span/><span class="ow">(+)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Nat'</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Nat'</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Nat'</span>
<span class="ow">(+)</span><span class="w"> </span><span class="kt">Z</span><span class="w"> </span>r<span class="w"> </span><span class="ow">=</span><span class="w"> </span>r
<span class="ow">(+)</span><span class="w"> </span><span class="ow">(</span><span class="kt">S</span><span class="w"> </span>l<span class="ow">)</span><span class="w"> </span>r<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">S</span><span class="w"> </span><span class="ow">(</span>l<span class="w"> </span><span class="ow">+</span><span class="w"> </span>r<span class="ow">)</span>
</pre></div>

<p>Now we can declare a vector type consisting of a size (<code>Nat'</code>) and a
type argument:</p>
<div class="highlight"><pre><span/><span class="kr">data</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Nat'</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Type</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Type</span><span class="w"> </span><span class="kr">where</span>
<span class="w">     </span><span class="nf">Nil</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span><span class="kt">Z</span><span class="w"> </span>a
<span class="w">     </span><span class="ow">(::)</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="ow">(</span>x<span class="w"> </span><span class="ow">:</span><span class="w"> </span>a<span class="ow">)</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="ow">(</span>xs<span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span>k<span class="w"> </span>a<span class="ow">)</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span><span class="ow">(</span><span class="kt">S</span><span class="w"> </span>k<span class="ow">)</span><span class="w"> </span>a
</pre></div>

<p>Here <code>a</code> is a type argument. <code>Vect'</code> has two constructors: <code>Nil</code>,
creating a <code>Vect'</code> of size <code>Z</code> containing elements of type <code>a</code> (0
elements) and <code>(::)</code>, which concatenates an object of type <code>a</code> with a
vector of size <code>k</code> of <code>a</code> and produces a vector of size <code>S k</code> containing
<code>a</code>.</p>

<p>Now to see dependent types in action, we can define <code>append'</code>, a
function that appends a vector to another vector:</p>
<div class="highlight"><pre><span/><span class="nf">append'</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span>n<span class="w"> </span>a<span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span>m<span class="w"> </span>a<span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span><span class="ow">(</span>n<span class="w"> </span><span class="ow">+</span><span class="w"> </span>m<span class="ow">)</span><span class="w"> </span>a
append'<span class="w"> </span><span class="kt">Nil</span><span class="w"> </span>ys<span class="w"> </span><span class="ow">=</span><span class="w"> </span>ys
append'<span class="w"> </span><span class="ow">(</span>x<span class="w"> </span><span class="ow">::</span><span class="w"> </span>xs<span class="ow">)</span><span class="w"> </span>ys<span class="w"> </span><span class="ow">=</span><span class="w"> </span>x<span class="w"> </span><span class="ow">::</span><span class="w"> </span>append'<span class="w"> </span>xs<span class="w"> </span>ys
</pre></div>

<p>The interesting part is the function signature - given a vector of size
<code>n</code> and a vector of size <code>m</code>, the resulting vector will have size
<code>n + m</code>. This information is captured in the declaration and the
compiler knows to apply the <code>(+)</code> defined above and type-check that this
is indeed true for a given pair of arguments.</p>

<h2>Proofs</h2>

<p>We can also attempt to define a <code>reverse'</code> function, which recursively
appends the head of the vector to the reversed tail:</p>
<div class="highlight"><pre><span/><span class="nf">reverse'</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span>n<span class="w"> </span>a<span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span>n<span class="w"> </span>a
reverse'<span class="w"> </span><span class="kt">Nil</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Nil</span>
reverse'<span class="w"> </span><span class="ow">(</span>x<span class="w"> </span><span class="ow">::</span><span class="w"> </span>xs<span class="ow">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span>append'<span class="w"> </span><span class="ow">(</span>reverse'<span class="w"> </span>xs<span class="ow">)</span><span class="w"> </span><span class="ow">[</span>x<span class="ow">]</span>
</pre></div>

<p>This doesn't compile though. We get the following error message:</p>
<div class="highlight"><pre><span/>When checking right hand side of reverse' with expected type
        Vect' (S k) a

Type mismatch between
        Vect' (k + S Z) a (Type of append' (reverse' xs) [x])
and
        Vect' (S k) a (Expected type)

Specifically:
        Type mismatch between
                k + S Z
        and
                S k
</pre></div>

<p>We are claiming the function returns a vector of the same length as the
input vector, but we haven't proven enough theorems about our definition
of natural numbers to convince the type checker. In this particular
case, the problem is that the compiler expects an <code>S k</code> but finds an
<code>k + S Z</code>. We need to prove that these are indeed equal
(<code>successor of k</code> is the same as <code>k + successor of Z</code>). Here is the
proof:</p>
<div class="highlight"><pre><span/><span class="nf">addOneProof</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="ow">(</span>n<span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Nat'</span><span class="ow">)</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">S</span><span class="w"> </span>n<span class="w"> </span><span class="ow">=</span><span class="w"> </span>n<span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="kt">S</span><span class="w"> </span><span class="kt">Z</span>
addOneProof<span class="w"> </span><span class="kt">Z</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Refl</span>
addOneProof<span class="w"> </span><span class="ow">(</span><span class="kt">S</span><span class="w"> </span>k<span class="ow">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span>cong<span class="w"> </span><span class="ow">(</span>addOneProof<span class="w"> </span>k<span class="ow">)</span>
</pre></div>

<p>Proofs are functions. There are a few things worth noting here: first,
the return type of this function is an equality (our theorem). Given a
natural <code>n</code>, the function proves that the equality holds. <code>Refl</code> is the
built-in reflexivity constructor, which constructs <code>x = x</code>. For the <code>Z</code>
case, we can use <code>Refl</code> to say that <code>S Z = Z + S Z</code> which is true by the
definition of <code>(+)</code>. For the <code>(S k)</code> case, we use <code>cong</code>. <code>cong</code> is a
built in function that states that equality holds after function
application. It's signature is <code>cong : (a = b) -&gt; f a = f b</code>, which
basically means if <code>a</code> is equal to <code>b</code>, then <code>f a</code> is equal to <code>f b</code>. In
our case, we are saying that if <code>addOneProof k</code> holds, then so does
<code>addOneProof (S k)</code>, which allows us to converge on the <code>Z</code> case.</p>

<p>We now have a proof that <code>S n = n + S Z</code>. With this, we can prove that
the type <code>Vect (k + (S Z)) a</code> can be rewritten as <code>Vect (S k) a</code>:</p>
<div class="highlight"><pre><span/><span class="nf">reverseProof</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span><span class="ow">(</span>k<span class="w"> </span><span class="ow">+</span><span class="w"> </span><span class="ow">(</span><span class="kt">S</span><span class="w"> </span><span class="kt">Z</span><span class="ow">))</span><span class="w"> </span>a<span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span><span class="ow">(</span><span class="kt">S</span><span class="w"> </span>k<span class="ow">)</span><span class="w"> </span>a
reverseProof<span class="w"> </span><span class="ow">{</span>k<span class="ow">}</span><span class="w"> </span>result<span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kr">rewrite</span><span class="w"> </span>addOneProof<span class="w"> </span>k<span class="w"> </span><span class="kr">in</span><span class="w"> </span>result
</pre></div>

<p>There is some Idris-specific syntax here: <code>{k}</code> brings <code>k</code> from the
function declaration in scope, so we can refer to it in the function
body even if it is not passed in as an argument. The <code>rewrite ... in</code>
expression applies the equality in the proof above to the input, in this
case effectively rewriting <code>Vect (k + (S Z)) a</code> to <code>Vect (S k) a</code>. Note
these proofs are evaluated at compile time and simply provide
information to the type checker. With this proof, we can implement
reverse like this:</p>
<div class="highlight"><pre><span/><span class="nf">reverse'</span><span class="w"> </span><span class="ow">:</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span>n<span class="w"> </span>a<span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Vect'</span><span class="w"> </span>n<span class="w"> </span>a
reverse'<span class="w"> </span><span class="kt">Nil</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Nil</span>
reverse'<span class="w"> </span><span class="ow">(</span>x<span class="w"> </span><span class="ow">::</span><span class="w"> </span>xs<span class="ow">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span>reverseProof<span class="w"> </span><span class="ow">(</span>append'<span class="w"> </span><span class="ow">(</span>reverse'<span class="w"> </span>xs<span class="ow">)</span><span class="w"> </span><span class="ow">[</span>x<span class="ow">])</span>
</pre></div>

<p>This is similar to the previous implementation, we just apply
<code>reverseProof</code> to the result of <code>append'</code>. This definition compiles.</p>

<h2>Thoughts About the Future</h2>

<p>Software development is generally driven by economics, where we more
often than not trade correctness for speed to market. But once the
software is up and running, correctness becomes an issue. As code
increases in complexity, the number of issues tends to increase, and the
velocity with which changes can be made without introducing regression
drops dramatically. We have various techniques that aim to maintain
stability, like automated testing, but these are not perfect: a test can
prove that for a given input we get an expected output, but cannot prove
that for <em>any</em> input we would get the expected output.</p>

<p>On the other hand, we have solutions that do eliminate entire classes of
issues. An example is typing. Python, Ruby, and JavaScript, all
dynamically typed, are extremely expressive and make it very easy to
whip up a proof of concept. But there is an entire class of type errors
which now turns into runtime issues. We are notoriously bad at
predicting what our code does, so the more help we get from machines to
ensure correctness, the better. In a strongly typed language, even
though it takes longer to convince the compiler that the code is
type-safe, this whole class of errors is eliminated. Language evolution
over the years tends to converge towards stronger typing: dynamic
languages are augmented with type checkers (Python has type hints,
JavaScript has TypeScript etc.) and statically typed languages are
becoming less verbose as type inference evolves. There will always be a
need for a quick prototype, but code we want to deem <em>reliable</em> should
be typed. This includes a wide range of business-critical applications
where errors are very costly.</p>

<p>I see Idris as the next step beyond this. Totality checking allows the
compiler to guarantee termination, eliminating hangs from the code.
First-order types allows us to push more information to the
type-checker, allowing for stricter type-checking. Proofs, expressed as
functions with regular syntax, allow the compiler to provide formal
verification of programs - here, as opposed to unit tests, we are
actually proving that we get the expected output for <em>any</em> input. These
are all tools for writing better, more correct code. As other functional
concepts got adopted over the years into more mainstream languages (for
example first-order functions, anonymous functions, algebraic types
etc.), I expect (and hope) these features to eventually be adopted too.</p>

<p>There is still a lot of room for improvement: writing proofs is tedious,
compiler errors are not always very clear, and, coming back to the speed
to market tradeoff, I doubt we will ever get to entire large
applications formally proven correct (barring some form of proof
inference to speed things up by a couple of orders of magnitude). That
being said, I would love to have these facilities as optional features
in other languages and at least have the ability to prove that the core
functionality of a component does what it is supposed to do, and get a
compile break whenever a regression is introduced.</p>

<p>Programming languages are continuously evolving and the future looks
exciting!</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>Idris also supports functions that produce an infinite stream of
values which can be used with lazy evaluation. The full definition
of totality includes functions which don't terminate but produce
<code>Inf</code>. This allows for non-terminating functions, but ensures
non-termination is intentional. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>I am using <code>'</code> to avoid naming conflicts with the built-in types
and functions. Idris already provides <code>Nat</code>, <code>Vect</code>, <code>append</code> and
<code>reverse</code>. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Thu, 20 Jul 2017 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/07/10/singletons.html</link>
      <guid>https://vladris.com/blog/2017/07/10/singletons.html</guid>
      <title><![CDATA[Singletons]]></title>
      <description><![CDATA[<h1>Singletons</h1>

<h2>Singletons are evil</h2>

<p>I will start off with a word of caution that singletons should be
avoided. Singleton is the object-oriented equivalent of a global
variable -- a piece of state which anyone can grab and modify, which
makes it hard to reason locally about code and generates ugly dependency
graphs. That being said, in a large system there are situations where
there is a legitimate need for global state or some component that
exposes a service to other components.</p>

<h2>Implementation</h2>

<p><a href="https://www.youtube.com/watch?v=23xDn3ReH7E">This CppCon lightning
talk</a> by Arno Lepisk covers
some implementation alternatives, suggesting that in most cases using a
namespace and flat functions is the simplest and best way to implement a
singleton:</p>
<div class="highlight"><pre><span/><span class="k">namespace</span><span class="w"> </span><span class="nn">Foo</span><span class="w"> </span><span class="p">{</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">DoFoo</span><span class="p">();</span>

<span class="p">}</span>
</pre></div>

<p>instead of:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Foo</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">DoFoo</span><span class="p">();</span>
<span class="p">};</span>

<span class="n">Foo</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">UseFoo</span><span class="p">();</span>
</pre></div>

<p>I completely agree with this, with the caveat that sometimes we do want
to inject dependencies and work against an interface instead of the
actual implementation, in which case the above approach might be
insufficient. Note that unless dependency injection is needed, the
default should be a namespace and flat functions.</p>

<h2>Dependency Injection</h2>

<p>Given an interface, an implementation, and a function to retrieve the
singleton like the following:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">IFoo</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">DoFoo</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>

<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">IFoo</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">IFoo</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">DoFoo</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/*...*/</span><span class="w"> </span><span class="p">};</span>
<span class="p">};</span>

<span class="n">IFoo</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">UseFoo</span><span class="p">();</span>
</pre></div>

<p>a common mistake I see is components directly calling the function like
this:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Component</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Bar</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">UseFoo</span><span class="p">().</span><span class="n">DoFoo</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>If the goal is to inject the dependency, for example have tests run
against <code>MockFoo</code>, this approach is not ideal. Code explicitly calls
<code>UseFoo</code> so the only way to switch implementation is to modify <code>UseFoo</code>
and provide some internal mechanism to change its return value. A better
approach is to have the client simply require an interface and provide
that at construction time:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Component</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="n">Component</span><span class="p">(</span><span class="n">IFoo</span><span class="o">&amp;</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">UseFoo</span><span class="p">())</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="n">m_foo</span><span class="p">(</span><span class="n">foo</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Bar</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_foo</span><span class="p">.</span><span class="n">DoFoo</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">IFoo</span><span class="o">&amp;</span><span class="w"> </span><span class="n">m_foo</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Note that in the above example we can create <code>Component</code> with a
<code>MockFoo</code> implementation of <code>IFoo</code> or some other implementation, which
is a better decoupling than directly calling <code>UseFoo</code> inside the member
functions of <code>Component</code>.</p>

<h2>Magic Statics</h2>

<p>By definition, a singleton should represent a unique object, so our
<code>UseFoo</code> needs to return the same reference on each call. Ensuring that
concurrent calls from multiple threads don't cause problems was
non-trivial until C++11, which introduced <q>magic statics</q>. Quote from
the C++ standard section 6.7:</p>

<blockquote>
<p>... such a variable [with static storage] is initialized the first
time control passes through its declaration; such a variable is
considered initialized upon the completion of its initialization. If
the initialization exits by throwing an exception, the initialization
is not complete, so it will be tried again the next time control
enters the declaration. If control enters the declaration concurrently
while the variable is being initialized, the concurrent execution
shall wait for completion of the initialization.</p>
</blockquote>

<p>The standard now guarantees that a static would only ever be created
once, and the simple way to implement a singleton (for example according
to Scott Meyer's <a href="https://www.goodreads.com/book/show/22800553-effective-modern-c">Effective Modern
C++</a>)
is:</p>
<div class="highlight"><pre><span/><span class="n">IFoo</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">UseFoo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Or the heap-allocated version:</p>
<div class="highlight"><pre><span/><span class="n">IFoo</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">UseFoo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="o">*</span><span class="n">instance</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<h2>Deterministic shutdown</h2>

<p>A more interesting problem which the above implementation doesn't cover
is deterministic shutdown. A local static, once created, will be live
for the duration of the program, which might not always be desirable.
Building on the previous implementation, here is a singleton which we
can also shutdown on demand:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Singleton</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">Use</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">static</span><span class="w"> </span><span class="k">auto</span><span class="o">&amp;</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">[]()</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="p">{</span>
<span class="w">            </span><span class="n">m_instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="o">*</span><span class="n">m_instance</span><span class="p">;</span>
<span class="w">        </span><span class="p">}();</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">Free</span><span class="p">()</span><span class="w"> </span><span class="k">noexcept</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_instance</span><span class="p">.</span><span class="n">reset</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_instance</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Singleton</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">m_instance</span><span class="p">;</span>

<span class="cm">/* ... */</span>

<span class="n">IFoo</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">UseFoo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">Singleton</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;::</span><span class="n">Use</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">FreeFoo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Singleton</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;::</span><span class="n">Free</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>Using this implementation, we can deterministically free the singleton
on demand via the <code>Free</code> function as opposed to having to wait for the
program to get unloaded, which can be useful in certain cases.</p>

<h2>Atomics</h2>

<p>Magic statics provide an easy way to guarantee we end up with a single
object, but the code generated to support this is non-trivial.
Disassembly of the <code>UseFoo</code> above as compiled by Clang 4.0.0 with <code>-O3</code>
flag:</p>
<div class="highlight"><pre><span/><span class="x">UseFoo():                             # @UseFoo()</span>
<span class="x">        push    rbx</span>
<span class="x">        mov     al, byte ptr [rip + guard variable for Singleton&lt;Foo&gt;::Use()::instance]</span>
<span class="x">        test    al, al</span>
<span class="x">        jne     .LBB0_6</span>
<span class="x">        mov     edi, guard variable for Singleton&lt;Foo&gt;::Use()::instance</span>
<span class="x">        call    __cxa_guard_acquire</span>
<span class="x">        test    eax, eax</span>
<span class="x">        je      .LBB0_6</span>
<span class="x">        mov     edi, 8</span>
<span class="x">        call    operator new(unsigned long)</span>
<span class="x">        mov     qword ptr [rax], vtable for Foo+16</span>
<span class="x">        mov     rdi, qword ptr [rip + Singleton&lt;Foo&gt;::m_instance]</span>
<span class="x">        mov     qword ptr [rip + Singleton&lt;Foo&gt;::m_instance], rax</span>
<span class="x">        test    rdi, rdi</span>
<span class="x">        je      .LBB0_5</span>
<span class="x">        mov     rax, qword ptr [rdi]</span>
<span class="x">        call    qword ptr [rax + 8]</span>
<span class="x">        mov     rax, qword ptr [rip + Singleton&lt;Foo&gt;::m_instance]</span>
<span class="x">.LBB0_5:</span>
<span class="x">        mov     qword ptr [rip + Singleton&lt;Foo&gt;::Use()::instance], rax</span>
<span class="x">        mov     edi, guard variable for Singleton&lt;Foo&gt;::Use()::instance</span>
<span class="x">        call    __cxa_guard_release</span>
<span class="x">.LBB0_6:</span>
<span class="x">        mov     rax, qword ptr [rip + Singleton&lt;Foo&gt;::Use()::instance]</span>
<span class="x">        pop     rbx</span>
<span class="x">        ret</span>
<span class="x">        mov     rbx, rax</span>
<span class="x">        mov     edi, guard variable for Singleton&lt;Foo&gt;::Use()::instance</span>
<span class="x">        call    __cxa_guard_abort</span>
<span class="x">        mov     rdi, rbx</span>
<span class="x">        call    _Unwind_Resume</span>
</pre></div>

<p>A lot of the generated code is the compiler implementing the guarantee
that on concurrent calls, a single intialization is performed. The
<code>Singleton</code> functions are inlined here since we are compiling with
<code>-O3</code>. We can provide a much more efficient implementation using an
atomic pointer on architectures where atomics are lock-free and we are
not worried about redundantly calling the constructor in the rare cases
of concurrent access that requires initialization:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Singleton</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">Use</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">auto</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m_instance</span><span class="p">.</span><span class="n">load</span><span class="p">();</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">instance</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">nullptr</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="o">*</span><span class="n">instance</span><span class="p">;</span>

<span class="w">        </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">T</span><span class="p">();</span>
<span class="w">        </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">nullptr</span><span class="p">;</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">m_instance</span><span class="p">.</span><span class="n">compare_exchange_strong</span><span class="p">(</span><span class="n">temp</span><span class="p">,</span><span class="w"> </span><span class="n">instance</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="o">*</span><span class="n">instance</span><span class="p">;</span>

<span class="w">        </span><span class="k">delete</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">*</span><span class="n">m_instance</span><span class="p">.</span><span class="n">load</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">Free</span><span class="p">()</span><span class="w"> </span><span class="k">noexcept</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">auto</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m_instance</span><span class="p">.</span><span class="n">exchange</span><span class="p">(</span><span class="nb">nullptr</span><span class="p">);</span>
<span class="w">        </span><span class="k">delete</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span><span class="w"> </span><span class="n">m_instance</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span><span class="w"> </span><span class="n">Singleton</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">m_instance</span><span class="p">;</span>

<span class="cm">/* ... */</span>

<span class="n">IFoo</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">UseFoo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">Singleton</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;::</span><span class="n">Use</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">FreeFoo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Singleton</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;::</span><span class="n">Free</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>The disassembly of the above <code>UseFoo</code> (built with the same compiler and
<code>-O3</code> flag) is:</p>
<div class="highlight"><pre><span/><span class="x">UseFoo():                             # @UseFoo()</span>
<span class="x">        push    rax</span>
<span class="x">        mov     rcx, qword ptr [rip + Singleton&lt;Foo&gt;::m_instance]</span>
<span class="x">        test    rcx, rcx</span>
<span class="x">        jne     .LBB0_3</span>
<span class="x">        mov     edi, 8</span>
<span class="x">        call    operator new(unsigned long)</span>
<span class="x">        mov     rcx, rax</span>
<span class="x">        mov     qword ptr [rcx], vtable for Foo+16</span>
<span class="x">        xor     eax, eax</span>
<span class="x">        lock</span>
<span class="x">        cmpxchg qword ptr [rip + Singleton&lt;Foo&gt;::m_instance], rcx</span>
<span class="x">        je      .LBB0_3</span>
<span class="x">        mov     rax, qword ptr [rcx]</span>
<span class="x">        mov     rdi, rcx</span>
<span class="x">        call    qword ptr [rax + 8]</span>
<span class="x">        mov     rcx, qword ptr [rip + Singleton&lt;Foo&gt;::m_instance]</span>
<span class="x">.LBB0_3:</span>
<span class="x">        mov     rax, rcx</span>
<span class="x">        pop     rcx</span>
<span class="x">        ret</span>
</pre></div>

<p>This code might new the object multiple times, but is guaranteed to
always return the same instance and retrieving it is more efficient than
relying on statics, since it uses a compare-exchange to guarantee
uniqueness. Many thanks to my colleague Vladimir Morozov who suggested
this approach.</p>

<h2>Tri-state</h2>

<p>We now have an efficient way to create and shutdown a singleton. If
shutdown, a subsequent call to <code>Use</code> would re-create the object. One
optional feature we can add is to enforce that once shutdown, a
singleton should never be accessed again. So instead of the two-state
<em>not initialized</em> and <em>live</em>, we can use three states: <em>not
initialized</em>, <em>live</em>, <em>freed</em> and terminate if an access is attempted in
the <em>freed</em> state:</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="kt">uintptr_t</span><span class="w"> </span><span class="n">FreedSingleton</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mh">0xDEADBEEF</span><span class="p">;</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Singleton</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">Use</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">auto</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Get</span><span class="p">();</span>

<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">instance</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="k">reinterpret_cast</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">FreedSingleton</span><span class="p">))</span>
<span class="w">            </span><span class="n">terminate</span><span class="p">();</span>

<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">*</span><span class="n">instance</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">Free</span><span class="p">()</span><span class="w"> </span><span class="k">noexcept</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">auto</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m_instance</span><span class="p">.</span><span class="n">exchange</span><span class="p">(</span><span class="k">reinterpret_cast</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">FreedSingleton</span><span class="p">));</span>
<span class="w">        </span><span class="k">delete</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">Get</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">auto</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">m_instance</span><span class="p">.</span><span class="n">load</span><span class="p">();</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">instance</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">nullptr</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>

<span class="w">        </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">T</span><span class="p">();</span>
<span class="w">        </span><span class="n">T</span><span class="o">*</span><span class="w"> </span><span class="n">temp</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">nullptr</span><span class="p">;</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">m_instance</span><span class="p">.</span><span class="n">compare_exchange_strong</span><span class="p">(</span><span class="n">temp</span><span class="p">,</span><span class="w"> </span><span class="n">instance</span><span class="p">))</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>

<span class="w">        </span><span class="k">delete</span><span class="w"> </span><span class="n">instance</span><span class="p">;</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">m_instance</span><span class="p">.</span><span class="n">load</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span><span class="w"> </span><span class="n">m_instance</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">atomic</span><span class="o">&lt;</span><span class="n">T</span><span class="o">*&gt;</span><span class="w"> </span><span class="n">Singleton</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">m_instance</span><span class="p">;</span>
</pre></div>

<p>We now have an efficient generic singleton which we can shutdown
on-demand and ensure clients never call after shutdown.</p>

<h2>Summary</h2>

<ul>
<li>Try not to use singletons, singletons are evil.</li>
<li>In most cases, a namespace and flat functions are enough, no need to
over-complicate things.</li>
<li>If dependency injection is required, make sure dependency is
properly injected during construction as opposed to member functions
directly calling the singleton-retrieving function.</li>
<li>Magic statics provide an easy way to implement singletons.</li>
<li>Atomics are more efficient than magic statics when they are
lock-free and we aren't worried about potentially having multiple
constructor calls in race cases.</li>
<li>If needed, singletons can be extended with a shutdown mechanism.</li>
<li>Three-state singletons can terminate on use-after-shutdown.</li>
</ul>
]]></description>
      <pubDate>Mon, 10 Jul 2017 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/04/07/data-structures-and-algorithms.html</link>
      <guid>https://vladris.com/blog/2017/04/07/data-structures-and-algorithms.html</guid>
      <title><![CDATA[Data Structures and Algorithms]]></title>
      <description><![CDATA[<h1>Data Structures and Algorithms</h1>

<p><q>Data Structures and Algorithms</q> is one of the basic CS courses. Data
structures and algorithms are also the building blocks of software. In
this post I will give a quick overview of data structures, algorithms,
and cover <em>iterators</em>, which bridge the two together.</p>

<h2>Data Structures</h2>

<p>As the name implies, data structures provide a way of structuring data,
in other words, they maintain some set of relationships between the
contained elements. Data structures are built around expected
access/update patterns and encapsulate the inherent tradeoffs. For
example, a queue models FIFO access (so accessing the last inserted
element requires dequeuing all elements which is <code>O(n)</code> for <code>n</code>
elements) while a stack models the opposite LIFO access (which can
access the last inserted element in <code>O(1)</code> but conversely makes
accessing the first element <code>O(n)</code> for <code>n</code> elements). A deque allows
elements to be inserted and removed from both front and back, but not
from the middle. On the other hand, inserting an element in a forward
list (where each node starting form head has a pointer to its successor)
can be done anywhere, but requires a traversal of the data structure up
to the insertion point (<code>O(n)</code>).</p>

<p>More complex data structures exist which model more complex
relationships between elements, for example graphs and trees.</p>

<p>In practice, while there are always complex situations which require the
use or development of exotic data structure, I consider those to be
exceptions - a few basic data structures are enough to solve most
problems. In fact, in most cases, simple linear data structures like
lists are sufficient.</p>

<p>It's worth noting that the relationships and access patterns modeled by
a data structure do not have anything to do with the type of the
contained data. A queue of integers or a queue of strings work in
exactly the same way. Generics provide a great mechanism to separate the
organizing structure from the data itself. Thus the C++ <code>std::vector&lt;T&gt;</code>
can provide a generic implementation of a heap array for any type <code>T</code>,
the same way a C# <code>List&lt;T&gt;</code> does. These generic data structure model how
the contained elements are laid out, but work with any provided type.</p>

<h2>Algorithms</h2>

<p>The dictionary definition of an algorithm is:</p>

<blockquote>
<p>noun: a process or set of rules to be followed in calculations or
other problem-solving operations, especially by a computer.</p>
</blockquote>

<p>There is a set of basic functions we can put our data through: search,
partition, rotate, sort, map, reduce, filter and so on. These functions
can be implemented in several ways, depending on the characteristics of
the input. For example, we can search for an element in <code>O(log n)</code> time
if our input is sorted and we can access it from the <q>middle</q> at no
extra cost. On the other hand, given unsorted data or a data structure
like a forward list which we can only access through its head, search
becomes an <code>O(n)</code> operation. The implementations of these functions are
what we call algorithms. In the examples above the algorithms are
<em>binary search</em> and <em>linear search</em>.</p>

<p>The same observation as with data structures applies: while there are
complex problems which require the development of brand new algorithms,
in practice, the vast majority of processing that we want to perform on
our data can be expressed either as a simple algorithm or a composition
of simple algorithms.</p>

<p>It is also interesting to note that the algorithms themselves are not
tied to a particular data type either, rather they only require certain
characteristics of their input. So we can perform a search as long as
there is some equivalence relation defined for the input data.
Similarly, we can perform a sort as long as there is a total order
relation defined on the input type. It doesn't really matter whether we
search for numbers or strings, the steps we take are the same.</p>

<p>Generics help here too, since they allow us to conceptually separate the
implementation of the algorithm (the steps) from the data we are
operating on. So the C++ <code>std::partition</code> algorithm can partition any
input -- given by a pair of forward iterators using any given predicate.
Similarly, the C# LINQ <code>Select</code> (known in most other languages as a
<code>map</code> operation), transforms all input values into output values given a
mapping function from the input type to the output type. We don't need
to implement a partition for ints, one for strings, and one for dates,
we need a generic partition which implements the steps of the algorithm
and works with any given data type.</p>

<h2>Iterators and Ranges</h2>

<p>Iterators act as the bridge between data structures and algorithms.
Iterators traverse a given data structure in a linear fashion, such that
an algorithm can process the input in a consistent manner, regardless of
the actual layout of the data. Note the data structure itself does not
need to be a linear one: a binary tree can be traversed with a preorder
iterator, or an inorder iterator, or a postorder iterator.</p>

<p>Algorithms work on ranges of data, which can be defined as a pair of
iterators (beginning and end) or an iterator and the number of available
elements (beginning and length). I will cover some of the C++ iterator
concepts since they are the most fleshed out. Other languages usually
rely on a subset of these.</p>

<p><strong>Input iterators</strong> can only be advanced and are one-pass only. These
map to input streams, for example unbuffered keyboard input where data
can be read once, but a subsequent read would yield different data.</p>

<p><strong>Forward iterators</strong> extend input iterators to multiple passes. For
example, a forward iterator models traversal of a forward list. We can
always re-start traversal from any saved position, but we cannot move
back (since nodes only have links to successors, not predecessors).</p>

<p><strong>Bidirectional iterators</strong> extend forward iterators to bidirectional
access. For example, a bidirectional iterator models traversal of a
doubly linked list. Here, we can move from one node in either direction
-- to its predecessor or to its successor.</p>

<p><strong>Random access iterators</strong> extend bidirectional iterators to random
access, meaning any element can be accessed in constant time. For
example, a random access iterator models traversal of an array. Here, we
can access any element at the same cost, since we don't need to perform
any traversal, simply index into the array.</p>

<p>Depending on the implementation of a given algorithm, different iterator
types might be required. The same function can sometimes be implemented
with several algorithms, having a more efficient version work with more
capable iterators and an alternative algorithm for less capable
iterators. For example we can implement an <code>O(n log n)</code> quicksort with a
random access iterator but we can also implement an <code>O(n^2)</code> bubblesort
that works with forward iterators.</p>

<p><code>IEnumerator&lt;T&gt;</code> in C# models a forward iterator. The (simplified)
interface is:</p>
<div class="highlight"><pre><span/><span class="k">interface</span><span class="w"> </span><span class="n">IEnumerator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">T</span><span class="w"> </span><span class="n">Current</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">get</span><span class="p">;</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">bool</span><span class="w"> </span><span class="nf">MoveNext</span><span class="p">();</span>
<span class="w">    </span><span class="k">void</span><span class="w"> </span><span class="nf">Reset</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>This allows us to advance the iterator and to reset it to the initial
position and re-start traversal, which is exactly what a forward
iterator does.</p>

<p>Lazy evaluation in some functional languages and generators (functions
that yield results) model input iterators which can be advanced in a
single pass.</p>

<p>While most relevant operations can be implemented with input iterators,
the resulting algorithms are not very efficient. For example, with a
bidirectional iterator, <code>reverse</code> can be implemented in <code>O(1)</code> space by
starting from both ends and swapping elements. On the other hand, given
an input iterator, <code>reverse</code> requires <code>O(n)</code> space as elements need to
be pushed onto a stack and popped in reverse order.</p>

<h2>Summary</h2>

<ul>
<li>Data structures model the relationship between elements and
encapsulate access patterns. Generic data structures provide a good
abstraction decoupling the structure of the data from the actual
contianed data.</li>
<li>Algorithms implement operations over data. Algorithms are grouped
together based on the function or transformation they implement.
Generic algorithms abstract the operational steps from the input the
algorithms operate on.</li>
<li>Iterators provide a bridge between data structures and algorithms.
The more capabilities an iterator has (ie. the more restrictions we
impose on the input), the more efficient the algorithm can be.
Similarly, most operations can be implemented in less efficent
manners (time and space-wise) on iterators with fewer capabilities
(ie. fewer restrictions imposed on the input).</li>
</ul>

<p>Recommended reading:</p>

<ul>
<li><a href="http://www.goodreads.com/book/show/23498372-from-mathematics-to-generic-programming">From Mathematics to Generic
Programming</a>
by Alexander A. Stepanov and Daniel E. Rose.</li>
<li><a href="https://www.goodreads.com/book/show/6142482-elements-of-programming">Elements o
Programming</a>
by Alexander A. Stepanov and Paul McJones.</li>
</ul>
]]></description>
      <pubDate>Fri, 07 Apr 2017 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/02/25/a-heterogeneous-event-store.html</link>
      <guid>https://vladris.com/blog/2017/02/25/a-heterogeneous-event-store.html</guid>
      <title><![CDATA[A Heterogeneous Event Store]]></title>
      <description><![CDATA[<h1>A Heterogeneous Event Store</h1>

<p>I recently stumbled upon a heterogeneous event collection which turned
out to pose an interesting design problem. We are using library code (we
can't change) that provides a templated <code>Event</code> to which we can
register callbacks and which we can raise later to invoke the callbacks.
The interface looks like this:</p>
<div class="highlight"><pre><span/><span class="cm">/* Library code */</span>
<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">Event</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// T is a callable object, like std::function</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Register</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">callback</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Register a callback */</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// Raises the event and forwards the arguments to the callbacks</span>
<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">Args</span><span class="o">&gt;</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Raise</span><span class="p">(</span><span class="n">Args</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">args</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Invoke all registered callbacks */</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>A stub implementation that validates client code is typed properly would
be:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">Event</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// T is a callable object, like std::function</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Register</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">callback</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="cm">/* Register a callback */</span>
<span class="w">        </span><span class="n">_callback</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">callback</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="c1">// Raises the event and forwards the arguments to the callbacks</span>
<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">Args</span><span class="o">&gt;</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Raise</span><span class="p">(</span><span class="n">Args</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">args</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="cm">/* Invoke all registered callbacks */</span>
<span class="w">        </span><span class="n">_callback</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span><span class="p">(</span><span class="n">args</span><span class="p">)...);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">T</span><span class="w"> </span><span class="n">_callback</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Note that unlike the real implementation, this only stores the last
registered event, but that is irrelevant for the purpose of this post.
I'm providing the code just to have something to compile against
(otherwise <code>Raise</code> would happily swallow any combination of arguments
passed to it). In reality, a more complex implementation would maintain
a list of callbacks, but this is sufficient for framing the design
problem.</p>

<p>The event collection which was wrapping a set of library events looked
like this:</p>
<div class="highlight"><pre><span/><span class="k">using</span><span class="w"> </span><span class="n">LaunchCallback</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">using</span><span class="w"> </span><span class="n">SaveCallback</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="p">)</span><span class="o">&gt;</span><span class="p">;</span>
<span class="k">using</span><span class="w"> </span><span class="n">ExitCallback</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">&gt;</span><span class="p">;</span>

<span class="k">class</span><span class="w"> </span><span class="nc">EventStore</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">OnLaunch</span><span class="p">(</span><span class="n">LaunchCallback</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">callback</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_launchEvent</span><span class="p">.</span><span class="n">Register</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">LaunchCallback</span><span class="o">&gt;</span><span class="p">(</span><span class="n">callback</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">OnSave</span><span class="p">(</span><span class="n">SaveCallback</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">callback</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_saveEvent</span><span class="p">.</span><span class="n">Register</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">SaveCallback</span><span class="o">&gt;</span><span class="p">(</span><span class="n">callback</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">OnExit</span><span class="p">(</span><span class="n">ExitCallback</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">callback</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_exitEvent</span><span class="p">.</span><span class="n">Register</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">ExitCallback</span><span class="o">&gt;</span><span class="p">(</span><span class="n">callback</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">RaiseLaunch</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_launchEvent</span><span class="p">.</span><span class="n">Raise</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">RaiseSave</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">fileName</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_saveEvent</span><span class="p">.</span><span class="n">Raise</span><span class="p">(</span><span class="n">fileName</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">RaiseExit</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_exitEvent</span><span class="p">.</span><span class="n">Raise</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">LaunchCallback</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_launchEvent</span><span class="p">;</span>
<span class="w">    </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">SaveCallback</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_saveEvent</span><span class="p">;</span>
<span class="w">    </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">ExitCallback</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_exitEvent</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Sample usage of the <code>EventStore</code>:</p>
<div class="highlight"><pre><span/><span class="n">EventStore</span><span class="w"> </span><span class="n">store</span><span class="p">;</span>

<span class="c1">// Register a couple of callbacks</span>
<span class="n">store</span><span class="p">.</span><span class="n">OnLaunch</span><span class="p">([]()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Do stuff */</span><span class="w"> </span><span class="p">});</span>
<span class="n">store</span><span class="p">.</span><span class="n">OnSave</span><span class="p">([](</span><span class="k">const</span><span class="w"> </span><span class="k">auto</span><span class="o">&amp;</span><span class="w"> </span><span class="n">arg</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Do stuff */</span><span class="w"> </span><span class="p">});</span>

<span class="c1">// Raise an event</span>
<span class="n">store</span><span class="p">.</span><span class="n">RaiseSave</span><span class="p">(</span><span class="s">"Some file name"</span><span class="p">);</span>
</pre></div>

<p>Looking at <code>EventStore</code>, it's obvious that there is a lot of repetition
involved: hooking up a new event involves aliasing a new callback,
adding a new member to the class, and adding the corresponding
registration and <code>Raise</code> member functions which end up being copy/pastes
of the other ones. There must be a better way!</p>

<p>An initial idea would be to use some sort of associative container
(hopefully something <a href="http://vladris.com/blog/2016/04/24/abusing-maps.html">better than an
unordered_map</a>),
but there is an interesting complication due to the fact that some of
the various events are actually of different types.
<code>Event&lt;std::function&lt;void()&gt;&gt;</code> has a different type than
<code>Event&lt;std::function&lt;void(const string&amp;)&gt;&gt;</code>. There are potential
workarounds to explore, like standardizing on a single type and
requiring clients to, for example, only use callbacks that do not take
any arguments. Another option would be to pass in some base object to
each event and let each callback re-interpret it. This takes us down the
wrong path though. We don't need to do any runtime lookup - the initial
code doesn't.</p>

<p>From the repetition in <code>EventStore</code>, it should become apparent that we
need some form of templated <code>Register</code> and <code>Raise</code> that would work for
each type of event we care about. A quick sketch of our function
signatures should look something like this:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="cm">/* ??? */</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">Register</span><span class="p">(</span><span class="cm">/* ??? */</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Register callback to the appropriate event</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="cm">/* ??? */</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">Args</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">Raise</span><span class="p">(</span><span class="n">Args</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Raise the appropriate event, forwarding args to it</span>
<span class="p">}</span>
</pre></div>

<p>It is also clear that we need a way to store all of the events we need
in our class. Since they are of heterogeneous types, we can't store
them in a map or equivalent, but we don't need to. <code>std::tuple</code> was
build exactly for this:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">Event</span><span class="o">&lt;</span><span class="n">LaunchCallback</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">           </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">SaveCallback</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">           </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">ExitCallback</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">m_events</span><span class="p">;</span>
</pre></div>

<p>Now the only remaining question is how to templatize our two member
functions to enable a lookup in the tuple. One approach would be to use
an enum:</p>
<div class="highlight"><pre><span/><span class="k">enum</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">EventType</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="kt">size_t</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">LaunchEvent</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">,</span>
<span class="w">    </span><span class="n">SaveEvent</span><span class="p">,</span>
<span class="w">    </span><span class="n">ExitEvent</span><span class="p">,</span>
<span class="p">};</span>
</pre></div>

<p>Given this enum, we can templatize on its values:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">EventStore</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="n">EventType</span><span class="w"> </span><span class="n">eventType</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Register</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">callback</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">size_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">eventType</span><span class="p">)</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m_events</span><span class="p">).</span><span class="n">Register</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">callback</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="n">EventType</span><span class="w"> </span><span class="n">eventType</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">Args</span><span class="o">&gt;</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Raise</span><span class="p">(</span><span class="n">Args</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">args</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">size_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">eventType</span><span class="p">)</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m_events</span><span class="p">).</span><span class="n">Raise</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span><span class="p">(</span><span class="n">args</span><span class="p">)...);</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">Event</span><span class="o">&lt;</span><span class="n">LaunchCallback</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">               </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">SaveCallback</span><span class="o">&gt;</span><span class="p">,</span>
<span class="w">               </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">ExitCallback</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">m_events</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Callers can use this new implementation like this:</p>
<div class="highlight"><pre><span/><span class="n">EventStore</span><span class="w"> </span><span class="n">store</span><span class="p">;</span>

<span class="c1">// Register a couple of callbacks</span>
<span class="n">store</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">EventType</span><span class="o">::</span><span class="n">LaunchEvent</span><span class="o">&gt;</span><span class="p">([]()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Do stuff */</span><span class="w"> </span><span class="p">});</span>
<span class="n">store</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">EventType</span><span class="o">::</span><span class="n">SaveEvent</span><span class="o">&gt;</span><span class="p">([](</span><span class="k">const</span><span class="w"> </span><span class="k">auto</span><span class="o">&amp;</span><span class="w"> </span><span class="n">arg</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Do stuff */</span><span class="w"> </span><span class="p">});</span>

<span class="c1">// Raise an event</span>
<span class="n">store</span><span class="p">.</span><span class="n">Raise</span><span class="o">&lt;</span><span class="n">EventType</span><span class="o">::</span><span class="n">SaveEvent</span><span class="o">&gt;</span><span class="p">(</span><span class="s">"Some file name"</span><span class="p">);</span>
</pre></div>

<p>With this implementation, we preserve the ability to have polymorphic
events but only need to implement the <code>Register</code> and <code>Raise</code> functions.
Adding a new event type now only requires aliasing the callback, adding
an enum member, and extending our member tuple by adding the new <code>Event</code>
to it.</p>

<p>The only drawback of this approach is the fact that we need to manually
keep the enum and the tuple in sync. This is not too bad, because if we
try to call <code>std::get</code> with a number higher than the size of the tuple,
we get a compile time error. If we accidentally swap two events, if they
are of incompatible types (for example <code>Event&lt;LaunchCallback&gt;</code> and
<code>Event&lt;SaveCallback&gt;</code>, as one expects callbacks of type
<code>std::function&lt;void()&gt;</code> and the other expects
<code>std::function&lt;void(const std::string&amp;)&gt;</code>), we get a compile-time error
because <code>Register</code> and <code>Raise</code> calls would fail to compile (attempting
to pass in callback/arguments of incompatible types). If we accidentally
swap two events of the same type, (<code>Event&lt;LaunchCallback&gt;</code> and
<code>Event&lt;ExitCallback&gt;</code>, since both <code>LaunchCallback</code> and <code>ExitCallback</code>
are aliased to the same <code>std::function&lt;void()&gt;</code>), runtime behavior is
equivalent, it just makes reading the code confusing. Now we end up
storing launch callbacks inside what we called <code>Event&lt;ExitCallback&gt;</code> and
vice-versa. Runtime is not affected, as we would also raise
<code>Event&lt;ExitCallback&gt;</code> by calling <code>Raise&lt;EventType::LaunchEvent&gt;</code>, but
it's not ideal. We could drop the aliases altogether and simply have:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">Event</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">&gt;&gt;</span><span class="p">,</span>
<span class="w">           </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">string</span><span class="o">&amp;</span><span class="p">)</span><span class="o">&gt;&gt;</span><span class="p">,</span>
<span class="w">           </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">m_events</span><span class="p">;</span>
</pre></div>

<p>This solves the above issues but is not very readable. There are other
options, like picking different names for the aliases - instead of
naming the event, have them name the type of callback. Either way,
effectively what we are doing is a mapping from an enum into a set of
<code>Event</code> types. We can actually push more information to the type system
and get rid of the need to do this mapping. We do that by making sure
our events are always of different types, even if the callback
signatures are the same. One way of achieving this is wrapping <code>Event</code>
and defining different types for each of our events:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">EventWrapper</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">m_event</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">LaunchEvent</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">EventWrapper</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">SaveEvent</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">EventWrapper</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="p">)</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">ExitEvent</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">EventWrapper</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
</pre></div>

<p>Note this is type information used only by the compiler and doesn't
bring any runtime overhead to our code. Inheritance is used here just so
we don't have to repeat declaring <code>m_event</code>, we could have just as well
declared each struct independently. Now we can update the member tuple
to store an event of each of these types:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">LaunchEvent</span><span class="p">,</span><span class="w"> </span><span class="n">SaveEvent</span><span class="p">,</span><span class="w"> </span><span class="n">ExitEvent</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_events</span><span class="p">;</span>
</pre></div>

<p>Since they are of different types, we no longer need an enum to index
into the tuple, we can do it by type (note <code>std::get</code> indexed by type
requires that the tuple contains distinct types, which is not the case
for <code>Event&lt;LaunchCallback&gt;</code> and <code>Event&lt;ExitCallback&gt;</code>, but it is for
<code>LaunchEvent</code> and <code>ExitEvent</code>):</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Callback</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">Register</span><span class="p">(</span><span class="n">Callback</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">callback</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m_events</span><span class="p">).</span><span class="n">m_event</span><span class="p">.</span><span class="n">Register</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">Callback</span><span class="o">&gt;</span><span class="p">(</span><span class="n">callback</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">Args</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">Raise</span><span class="p">(</span><span class="n">Args</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m_events</span><span class="p">).</span><span class="n">m_event</span><span class="p">.</span><span class="n">Raise</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span><span class="p">(</span><span class="n">args</span><span class="p">)...);</span>
<span class="p">}</span>
</pre></div>

<p>The <code>Callback</code> template argument in <code>Register</code> can be deduced once <code>T</code>
is specified. The full implementation is:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">EventWrapper</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Event</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">function</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">m_event</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">LaunchEvent</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">EventWrapper</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">SaveEvent</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">EventWrapper</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="p">)</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">ExitEvent</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">EventWrapper</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>

<span class="k">class</span><span class="w"> </span><span class="nc">EventStore</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Callback</span><span class="o">&gt;</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Register</span><span class="p">(</span><span class="n">Callback</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">callback</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m_events</span><span class="p">).</span><span class="n">m_event</span><span class="p">.</span><span class="n">Register</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">Callback</span><span class="o">&gt;</span><span class="p">(</span><span class="n">callback</span><span class="p">));</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">Args</span><span class="o">&gt;</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Raise</span><span class="p">(</span><span class="n">Args</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="n">args</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m_events</span><span class="p">).</span><span class="n">m_event</span><span class="p">.</span><span class="n">Raise</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">forward</span><span class="o">&lt;</span><span class="n">Args</span><span class="o">&gt;</span><span class="p">(</span><span class="n">args</span><span class="p">)...);</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span><span class="n">LaunchEvent</span><span class="p">,</span><span class="w"> </span><span class="n">SaveEvent</span><span class="p">,</span><span class="w"> </span><span class="n">ExitEvent</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_events</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Callers can use it like this:</p>
<div class="highlight"><pre><span/><span class="n">EventStore</span><span class="w"> </span><span class="n">store</span><span class="p">;</span>

<span class="c1">// Register a couple of callbacks</span>
<span class="n">store</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">LaunchEvent</span><span class="o">&gt;</span><span class="p">([]()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Do stuff */</span><span class="w"> </span><span class="p">});</span>
<span class="n">store</span><span class="p">.</span><span class="n">Register</span><span class="o">&lt;</span><span class="n">SaveEvent</span><span class="o">&gt;</span><span class="p">([](</span><span class="k">const</span><span class="w"> </span><span class="k">auto</span><span class="o">&amp;</span><span class="w"> </span><span class="n">arg</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* Do stuff */</span><span class="w"> </span><span class="p">});</span>

<span class="c1">// Raise an event</span>
<span class="n">store</span><span class="p">.</span><span class="n">Raise</span><span class="o">&lt;</span><span class="n">SaveEvent</span><span class="o">&gt;</span><span class="p">(</span><span class="s">"Some file name"</span><span class="p">);</span>
</pre></div>

<p>In this case, adding a new event requires declaring a new struct and
adding it to the tuple. Since we are retrieving the event by its type,
no mapping is involved.</p>
]]></description>
      <pubDate>Sat, 25 Feb 2017 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2017/02/20/memory-management.html</link>
      <guid>https://vladris.com/blog/2017/02/20/memory-management.html</guid>
      <title><![CDATA[Memory Management]]></title>
      <description><![CDATA[<h1>Memory Management</h1>

<p>Memory management involves handling memory resources allocated for a
certain task, ensuring that the memory is freed once it is no longer
needed so it can be reused for some other task. If the memory is not
freed in a timely manner, the system might run out of resources or incur
degraded performance. A memory resource that is never freed once no
longer needed is called a leak - the resource becomes unusable, usually
for the duration of the process. Another issue is <em>use after free</em>, in
which a memory resource that was already freed is used as if it wasn't.
This usually causes unexpected behavior as the code is trying to read,
modify or wrongly interpret data at a memory location. Memory management
can be <em>manual</em> - with code explicitly handling deallocation, or
<em>automatic</em>, in which memory gets freed once no longer needed by an
automated process.</p>

<h2>Manual Memory Management</h2>

<p>Manual memory management is efficient, since allocations and
deallocations don't incur any overhead. In C:</p>
<div class="highlight"><pre><span/><span class="k">typedef</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">_Foo</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">}</span><span class="w"> </span><span class="n">Foo</span><span class="p">;</span>

<span class="p">...</span>

<span class="n">Foo</span><span class="o">*</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Foo</span><span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">Foo</span><span class="p">));</span>

<span class="p">...</span>

<span class="n">free</span><span class="p">(</span><span class="n">foo</span><span class="p">);</span>
</pre></div>

<p>The disadvantage of this approach, and the main reason automatic memory
management models were invented, is that this puts the developer in
charge of making sure memory doesn't leak and that it is not used after
it is freed. As the complexity of the code increases, this becomes
increasingly difficult. As pointers are passed around the system and get
stored in various data structures, it becomes difficult to know given
some pointer that is no longer needed whether: a) this was the very last
piece of code that actually needed to access the location pointed to by
this pointer, in which case the memory should be freed, and b) whether
the memory this pointer is pointing to is still valid and hasn't been
freed previously.</p>

<h2>Automatic Memory Management</h2>

<p>Automatic memory management attempts to move the responsibility of
tracking when a memory resource is no longer needed (and handling its
deallocation) from the developer to the system. Such a system is called
<em>garbage collected</em>, as memory that is no longer needed (<q>garbage</q>) is
reclaimed by the system automatically. The two most popular methods used
to automatically free memory are <em>tracing garbage collectors</em> and
<em>reference counting</em>.</p>

<h3>Tracing Garbage Collector</h3>

<p>Tracing garbage collectors work by tracing references to objects on the
heap and checking whether a given resource allocated on the heap has at
least one reference path to it from the stack. If such a path exists, it
means that from the stack (an argument to a function, a local variable),
there is a way to perform a set of dereference and access the memory
resource. If such a path doesn't exist, it means the memory is
unreachable, so regardless of how executing code accesses other objects
on the heap, there is no way to access this resource - which means the
memory can be safely deallocated.</p>

<p>For example, a naÃ¯ve tracing garbage collection algorithm,
<em>mark-and-sweep</em>, involves adding an <q>in-use</q> bit to each memory
resource allocated then, during collection, following all references
starting from the stack and marking each as <q>in-use</q>. Once all used
resources are marked, the sweep stage involves walking the whole heap
and for each memory resource, if not marked as <q>in-use</q>, freeing it.</p>

<p>Tracing garbage collectors are used by many popular runtimes, like JVM
and .NET. In C#:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Bar</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>
<span class="p">}</span>

<span class="p">...</span>

<span class="p">{</span>
<span class="w">    </span><span class="n">Foo</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Foo</span><span class="p">();</span>
<span class="w">    </span><span class="n">foo</span><span class="p">.</span><span class="n">bar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Bar</span><span class="p">();</span>

<span class="w">    </span><span class="c1">// there is no stack variable pointing to the Bar object, but it can</span>
<span class="w">    </span><span class="c1">// still be reached through foo (foo.bar), so there exists a path from</span>
<span class="w">    </span><span class="c1">// the stack to it, meaning code can still access it.</span>
<span class="p">}</span>

<span class="c1">// foo goes out of scope which means neither foo nor its member Bar can be</span>
<span class="c1">// accessed any longer, so they can be safely collected</span>
</pre></div>

<p>There are a couple of disadvantages with the tracing GC approach: first,
the system needs to ensure memory resources are not being allocated
while a garbage collection is taking place. This means code execution is
paused during collection, which obviously impacts performance. The
second disadvantage of this approach is that the system is not as lean
as other memory management models: memory resources are kept allocated
longer than really needed, for the time interval between the last
reference to them goes out of scope until the actual collection is
performed.</p>

<h3>Reference Counting</h3>

<p>An alternative to tracing garbage collectors is reference counting. As
the name implies, a memory resource in such a system has an associated
reference count -the number of references to it. As soon as the last
reference goes out of scope, when the reference count reaches zero, the
memory can be safely deallocated. Unlike tracing, reference counting is
performed as code executes: the count of a given memory resource is
automatically increased with each assignment where the resource is on
the right-hand-side, and is automatically decreased whenever a reference
goes out of scope.</p>

<p>Python manages memory using reference counting:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Foo</span><span class="p">:</span> <span class="k">pass</span>

<span class="c1"># allocate Foo, its reference count is 1</span>
<span class="n">foo1</span> <span class="o">=</span> <span class="n">Foo</span><span class="p">()</span>

<span class="c1"># reference count is 2 after assignment</span>
<span class="n">foo2</span> <span class="o">=</span> <span class="n">foo1</span>

<span class="o">...</span>
<span class="c1"># once foo1 and foo2 go out of scope, reference count becomes 0 and memory</span>
<span class="c1"># is automatically freed</span>
</pre></div>

<p>C++ smart pointers work in a similar manner:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>

<span class="p">...</span>

<span class="c1">// foo1 is a shared_ptr pointing to a Foo stored on the heap. Reference</span>
<span class="c1">// count for the Foo object is 1</span>
<span class="k">auto</span><span class="w"> </span><span class="n">foo1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span>

<span class="c1">// reference count becomes 2 after assignment</span>
<span class="k">auto</span><span class="w"> </span><span class="n">foo2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo1</span><span class="p">;</span>

<span class="p">...</span>
<span class="c1">// Once foo1 and foo2 go out of scope, reference count becomes 0 and memory</span>
<span class="c1">// is automatically freed</span>
</pre></div>

<p>The main advantages over tracing garbage collection are the fact that
execution doesn't need to be paused in order to reclaim memory and that
resources are deallocated as soon as they are no longer used (once
reference count becomes 0). There are also several disadvantages with
this approach: first, each memory resource needs to store an additional
reference count and updating the reference count in a multi-threaded
environment needs to be performed atomically. Second, and most
important, this memory management model does not handle <em>reference
cycles</em>.</p>

<p>Reference cycles occur when two heap objects hold references to each
other even after no longer being reachable from the stack. In this case,
a tracing garbage collector would mark the objects as being unreachable
and deallocate them, but simple reference counting would not be able to
identify this - from that point of view, each object is being referred
to by another object thus it should not be collected. Example of
reference cycle in Python:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Foo</span><span class="p">:</span> <span class="k">pass</span>

<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">Foo</span><span class="p">(),</span> <span class="n">Foo</span><span class="p">()</span>
<span class="n">a</span><span class="o">.</span><span class="n">other</span><span class="p">,</span> <span class="n">b</span><span class="o">.</span><span class="n">other</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span>
<span class="c1"># a.other holds a reference to b, b.other holds a reference to a</span>
<span class="c1"># even when a and b go out of scope, the "other" attributes still hold references</span>
<span class="c1"># to the objects so their reference count would not drop to 0</span>
</pre></div>

<p>A similar example in C++:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="w"> </span><span class="n">other</span><span class="p">;</span>
<span class="p">};</span>

<span class="p">...</span>

<span class="k">auto</span><span class="w"> </span><span class="n">foo1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span>
<span class="k">auto</span><span class="w"> </span><span class="n">foo2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span>

<span class="n">foo1</span><span class="o">-&gt;</span><span class="n">other</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo2</span><span class="p">;</span>
<span class="n">foo2</span><span class="o">-&gt;</span><span class="n">other</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo1</span><span class="p">;</span>
<span class="c1">// there are two references to each Foo object: foo1 and foo2-&gt;other for the first</span>
<span class="c1">// object, foo2 and foo1-&gt;other for the second object. Even if the foo1 and foo2</span>
<span class="c1">// variables go out of scope, neither of the objects would be collected due to the</span>
<span class="c1">// extra reference</span>
</pre></div>

<p>Python and C++ solve this problem in different ways: Python supplements
reference counting with a tracing garbage collector. So while most of
the memory management is done via reference counting, a tracing garbage
collector is still employed to clean up cycles like in the above
example. This hybrid approach has he pros and cons of both of the
mechanisms discussed above. C++ avoids the execution pauses a tracing
garbage collectors would create by, instead, leveraging <em>weak
references</em>. Weak or non-owning references point to an object but do not
prevent it from being collected when all <em>strong</em> references go away.
There are several ways to express a non-owning reference, with different
advantages and drawbacks:</p>

<ul>
<li>A <code>&amp;</code> reference has to be assigned on construction and cannot be
re-assigned after being bound to an object. If used after the
underlying object was destroyed, it causes undefined behavior.</li>
<li>A <code>*</code> pointer can be <code>nullptr</code>-initialized and assigned later or
re-assigned. Similarly, if used after the pointed-to object was
destroyed, causes undefined behavior.</li>
<li>A <code>weak_ptr&lt;T&gt;</code> is a standard library type implementing a non-owning
reference. A <code>weak_ptr</code> can be converted to a <code>shared_ptr</code> (using
its <code>lock()</code> method). If there is no strong (<code>shared_ptr</code>) reference
to an object it gets destroyed, regardless of how many <code>weak_ptr</code>
instances point to it. But once a <code>weak_ptr</code> successfully locks an
object, it creates a strong reference which ensures the object is
kept alive. The drawback of using <code>weak_ptr</code> is additional overhead:
the control block of a smart pointer needs to store both strong and
weak reference count (with similar atomic reference counting), and,
even if an object gets destroyed because all strong references went
out of scope, the control block stays alive until all weak
references go away too.</li>
</ul>

<p>Updating the <code>Foo</code> struct in the example above to use a <code>weak_ptr</code>
instead, the reference cycle is avoided:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">weak_ptr</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="w"> </span><span class="n">other</span><span class="p">;</span>
<span class="p">};</span>

<span class="p">...</span>

<span class="k">auto</span><span class="w"> </span><span class="n">foo1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span>
<span class="k">auto</span><span class="w"> </span><span class="n">foo2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span>

<span class="n">foo1</span><span class="o">-&gt;</span><span class="n">other</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo2</span><span class="p">;</span>
<span class="n">foo2</span><span class="o">-&gt;</span><span class="n">other</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo1</span><span class="p">;</span>
<span class="c1">// now the two Foo objects have only one strong reference to them through</span>
<span class="c1">// the foo1 and foo2 variables The other pointers are weak references which</span>
<span class="c1">// won't prevent the objects from being destroyed when foo1 and foo2 go out</span>
<span class="c1">// of scope</span>
</pre></div>

<h3>Ownership and Lifetimes</h3>

<p>An alternative way to think about heap objects is in terms of
<em>ownership</em> and <em>lifetime</em>. In this model, a heap object is uniquely
owned by some other object and gets freed automatically when the owner
is destructed. In C++, this is achieved through <code>unique_ptr</code>:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">Bar</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>

<span class="p">...</span>

<span class="p">{</span>
<span class="w">    </span><span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span><span class="w"> </span><span class="c1">// this creates a Foo object on the heap, owned by bar</span>
<span class="p">}</span>
<span class="c1">// the heap object gets freed once bar gets freed</span>
</pre></div>

<p>Ownership of the object can be transferred by moving the <code>unique_ptr</code>.
The main advantage of this model is that it has no overhead - unlike
tracing memory which involves pausing execution or reference counting
which involves atomic count of references, a <code>unique_ptr</code> is just a
wrapper over a pointer.</p>

<p>Unique pointers cannot be copied though (by definition, otherwise there
would no longer denote unique ownership), so when other code needs to
access the heap object, it would need to get a reference from the owning
object:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">UseFoo</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Foo</span><span class="o">&amp;</span><span class="w"> </span><span class="n">foo</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">}</span>

<span class="p">...</span>

<span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>

<span class="n">UseFoo</span><span class="p">(</span><span class="o">*</span><span class="n">bar</span><span class="p">.</span><span class="n">foo</span><span class="p">);</span>
</pre></div>

<p>The problem with this approach is that if another object ends up holding
on to a reference which outlives the owning object, the reference
becomes dangling and refers to an object which was already freed. This
becomes the equivalent of a <em>use after free</em>, so here is where the
concept of <em>lifetime</em> becomes important: none of the non-owning
references of a uniquely owned heap object should outlive the object.</p>

<p>Unfortunately in C++ this has to be handled through sensical design and
is mostly left up to the developer. Rust on the other hand provides
strong static analysis and lifetime annotations to ensure such issues do
not occur. In fact, the default in Rust is to have uniquely owned
objects which can be <q>borrowed</q> when needed and static analysis
ensures no dangling references appear. In C++:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">Bar</span><span class="p">{</span>
<span class="w">    </span><span class="n">Foo</span><span class="o">*</span><span class="w"> </span><span class="n">foo</span><span class="p">;</span>
<span class="p">};</span>

<span class="p">...</span>

<span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Foo</span><span class="w"> </span><span class="n">foo</span><span class="p">;</span>
<span class="w">    </span><span class="n">bar</span><span class="p">.</span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="n">foo</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">// bar.foo is now a dangling pointer since Foo was freed</span>
</pre></div>

<p>The above example used a pointer for simplicity, since a <code>&amp;</code> reference
(<code>Foo&amp;</code>) needs to be bound at construction time, but same applies for
that type of reference: once an object gets freed, &amp; references and
non-owning pointers to it are left dangling. On the other hand, this
does not compile in Rust:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">Foo</span><span class="w"> </span><span class="p">{</span>
<span class="p">}</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">Bar</span><span class="o">&lt;'</span><span class="na">a</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">foo</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="o">'</span><span class="na">a</span><span class="w"> </span><span class="nc">Foo</span>
<span class="p">}</span>

<span class="o">..</span><span class="p">.</span>

<span class="kd">let</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>
<span class="p">{</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Foo</span><span class="w"> </span><span class="p">{};</span>
<span class="w">    </span><span class="n">bar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Bar</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">foo</span><span class="p">:</span><span class="w"> </span><span class="kp">&amp;</span><span class="nc">foo</span><span class="w"> </span><span class="p">};</span>
<span class="p">}</span>
<span class="c1">// compiler correctly shows `foo` dropped here while still borrowed</span>
</pre></div>

<p>In Rust, the compiler ensures dangling references (<q>borrowed</q> objects)
do not exist once owning object goes out of scope.</p>

<p>It seems that in most cases, the best approach to memory management is
to use the latter model of ownership and lifetimes which comes with no
runtime overhead and handle the dangling reference problem through
static analysis. The advantages of this approach extend beyond the
runtime cost of other automatic memory management techniques to a model
which also works well in a multi-threaded environment, eg. if we only
allow the owner of an object to modify it, we can eliminate certain data
races. From a systems design perspective it is also an advantage to have
a clear understanding of ownership throughout the system.</p>

<h2>Summary</h2>

<p>This post covered several memory management techniques, outlining their
pros and cons:</p>

<ul>
<li>Manual - human error prone.</li>
<li>Automatic using a tracing garbage collector - safe but comes with
runtime overhead.</li>
<li>Automatic using reference counting - smaller runtime cost than a
tracing garbage collector but needs additional mechanisms to deal
with reference cycles.</li>
<li>Concepts of ownership and lifetime - no runtime overhead, but should
be supplemented by static analysis to avoid dangling references.</li>
</ul>
]]></description>
      <pubDate>Mon, 20 Feb 2017 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/12/03/notes-on-error-handling.html</link>
      <guid>https://vladris.com/blog/2016/12/03/notes-on-error-handling.html</guid>
      <title><![CDATA[Notes on Error Handling]]></title>
      <description><![CDATA[<h1>Notes on Error Handling</h1>

<p>I recently read Joe Duffy's excellent blog post <a href="http://joeduffyblog.com/2016/02/07/the-error-model/">The Error
Model</a>. Joe worked
on Midori and has some great insights on error model design. I wanted to
write down a couple of personal notes on error handling.</p>

<h2>Using the Type System</h2>

<p>Before even talking about error scenarios, it's worth pointing out that
there are categories of errors where the type system helps if not to
eliminate them, at least to scope them and prevent them from propagating
unchecked throughout the system.</p>

<h3>Arguments</h3>

<p>In many cases, an error means the value of some variable has an invalid
value. If this invalid value is passed down to called functions, it can
manifests itself deep in the stack when it could've been caught
earlier. A simple example would be move directions for a game - let's
say the player can move <code>Up</code>, <code>Down</code>, <code>Left</code>, or <code>Right</code>. This can be
encoded as:</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">UP</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">LEFT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">DOWN</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">2</span><span class="p">;</span>
<span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">RIGHT</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">3</span><span class="p">;</span>

<span class="p">...</span>

<span class="kt">void</span><span class="w"> </span><span class="n">move</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">direction</span><span class="p">,</span><span class="w"> </span><span class="n">player</span><span class="w"> </span><span class="n">player</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="n">direction</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="no">UP</span><span class="p">:</span><span class="w"> </span><span class="n">player</span><span class="p">.</span><span class="n">move_up</span><span class="p">();</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="no">LEFT</span><span class="p">:</span><span class="w"> </span><span class="n">player</span><span class="p">.</span><span class="n">move_left</span><span class="p">();</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="no">DOWN</span><span class="p">:</span><span class="w"> </span><span class="n">player</span><span class="p">.</span><span class="n">move_down</span><span class="p">();</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="no">RIGHT</span><span class="p">:</span><span class="w"> </span><span class="n">player</span><span class="p">.</span><span class="n">move_right</span><span class="p">();</span><span class="w"> </span><span class="k">break</span><span class="p">;</span>
<span class="w">        </span><span class="k">default</span><span class="o">:</span>
<span class="w">            </span><span class="c1">// direction should only be 0, 1, 2, 3</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>but ultimately a caller can still pass any int value to this function
which would end up in the default branch as a direction the code
doesn't know how to handle. The alternative is, of course:</p>
<div class="highlight"><pre><span/><span class="k">enum</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">direction</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">up</span><span class="p">,</span>
<span class="w">    </span><span class="n">left</span><span class="p">,</span>
<span class="w">    </span><span class="n">down</span><span class="p">,</span>
<span class="w">    </span><span class="n">right</span>
<span class="p">};</span>

<span class="p">...</span>

<span class="kt">void</span><span class="w"> </span><span class="n">move</span><span class="p">(</span><span class="n">direction</span><span class="w"> </span><span class="n">direction</span><span class="p">,</span><span class="w"> </span><span class="n">player</span><span class="w"> </span><span class="n">player</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">}</span>
</pre></div>

<p>In this case, the type system ensures direction can only possibly hold
one of the allowed values. This is a trivial example but there are many
more interesting ones. Take for example some connection which, if
opened, can receive data and close and, if not opened, can be opened.
This can be modelled like this:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">connection</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">open</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">is_opened</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* error, connection already opened */</span><span class="w"> </span><span class="p">}</span>
<span class="w">        </span><span class="p">...</span>
<span class="w">    </span><span class="p">};</span>

<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">close</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">is_opened</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* error, connection not opened */</span><span class="w"> </span><span class="p">}</span>
<span class="w">        </span><span class="p">...</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">receive</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">is_opened</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* error, connection not opened */</span><span class="w"> </span><span class="p">}</span>
<span class="w">        </span><span class="p">...</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="kt">bool</span><span class="w"> </span><span class="n">is_opened</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Here we have to handle various cases where we try to perform an
open-connection operation on a connection that hasn't been opened yet,
and vice-versa. Another way to model this (as of C++17) is using a
variant and separate types for open and closed connections:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">opened_connection</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">close</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">receive</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">closed_connection</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">open</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">...</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">using</span><span class="w"> </span><span class="n">connection</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">variant</span><span class="o">&lt;</span><span class="n">closed_connection</span><span class="p">,</span><span class="w"> </span><span class="n">opened_connection</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>Here, as long as we have a <code>closed_connection</code> instance, we can only
perform closed-connection operations and as long as we have an
<code>open_connection</code> instance, we can only perform opened-connection
operations. The error states we had to handle above go away as the type
system ensures we can never call <code>receive</code> on a closed connection etc.</p>

<h3>Return Values</h3>

<p>The type system can also be leveraged to embellish return types as an
alternative to using return codes. For example, assume we have a
function which parses a phone number provided by the user into some
<code>phone_number_t</code> used internally. There are a few ways to implement
this:</p>
<div class="highlight"><pre><span/><span class="n">phone_number_t</span><span class="w"> </span><span class="nf">parse_phone_number</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">input</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">phone_number_t</span><span class="o">::</span><span class="n">is_valid</span><span class="p">(</span><span class="n">input</span><span class="p">))</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">phone_number_t</span><span class="o">::</span><span class="n">from_string</span><span class="p">(</span><span class="n">input</span><span class="p">);</span><span class="w"> </span><span class="c1">// assume we can construct a phone_number_t from a valid string</span>
<span class="w">    </span><span class="k">else</span>
<span class="w">        </span><span class="k">throw</span><span class="w"> </span><span class="n">invalid_phone_number</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>This is not ideal though, since exception should really be exceptional
(more on this below), and user providing invalid input should be a
completely valid scenario. The alternative would be to use a return
code:</p>
<div class="highlight"><pre><span/><span class="kt">bool</span><span class="w"> </span><span class="nf">parse_phone_number</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">input</span><span class="p">,</span><span class="w"> </span><span class="n">phone_number_t</span><span class="o">&amp;</span><span class="w"> </span><span class="n">output</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">phone_number_t</span><span class="o">::</span><span class="n">is_valid</span><span class="p">(</span><span class="n">input</span><span class="p">))</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="nb">false</span><span class="p">;</span>

<span class="w">    </span><span class="n">output</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">phone_number_t</span><span class="o">::</span><span class="n">from_string</span><span class="p">(</span><span class="n">input</span><span class="p">);</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This works, but calling code is uglier:</p>
<div class="highlight"><pre><span/><span class="k">auto</span><span class="w"> </span><span class="n">phone_number</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_phone_number</span><span class="p">(</span><span class="n">input</span><span class="p">);</span>
</pre></div>

<p>now becomes:</p>
<div class="highlight"><pre><span/><span class="n">phone_number_t</span><span class="w"> </span><span class="n">phone_number</span><span class="p">;</span>
<span class="kt">bool</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">parse_phone_number</span><span class="p">(</span><span class="n">input</span><span class="p">,</span><span class="w"> </span><span class="n">phone_number</span><span class="p">);</span>
</pre></div>

<p>We can also end up in a bad state if we forget to check the return
value. The alternative is to encode the information that we either have
a <code>phone_number_t</code> or an invalid number in a type. In C++ we have (as of
C++17) <code>optional&lt;T&gt;</code> for this:</p>
<div class="highlight"><pre><span/><span class="n">optional</span><span class="o">&lt;</span><span class="n">phone_number_t</span><span class="o">&gt;</span><span class="w"> </span><span class="n">parse_phone_number</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">input</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">phone_number_t</span><span class="o">::</span><span class="n">is_valid</span><span class="p">(</span><span class="n">input</span><span class="p">))</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">nullopt</span><span class="p">;</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">phone_number_t</span><span class="o">::</span><span class="n">from_string</span><span class="p">(</span><span class="n">input</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>This is not quite a return error code and cannot really be ignored -
there is no implicit case from <code>optional&lt;T&gt;</code> to <code>T</code>, so callers need to
explicitly handle the case when the operation failed. Calling this is as
natural as the throwing version, but does not rely on exceptions<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>.
This is also called <em>monadic error handling</em> and is widely employed by
functional languages. I find this a good alternative to throwing
exceptions as long as it is well scoped and error checks don't have to
pollute too many functions in the call stack.</p>

<h2>Preconditions</h2>

<p>Preconditions are conditions that should be satisfied upon entering a
function to ensure the function works as expected. When a function is
called but the preconditions are not met, it is not an error, it is a
developer bug. The recommended way of handling such a situation is, if
possible, to crash immediately. The reason for crashing is that calling
a function with preconditions not being met means the system is an
invalid state and attempting recovery is usually not worth it. Crashing
on the other hand would provide developers with dumps to help understand
how the system got into this state and fix the underlying bug.</p>

<p>The alternative to this is undefined behavior - calling a function
without meeting the preconditions cannot guarantee anything about the
execution of the function. Undefined behavior is used extensively
throughout the C++ standard <sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>. While failing fast is the preferred
approach, sometimes it is unfeasible to check preconditions at runtime:
for example a precondition of binary search is that it searches over an
ordered range. Performing a binary search takes logarithmic time but
validating that a range is ordered takes linear time, so adding this
check would negatively impact the run time of the algorithm. In this
case, it is OK to say that we cannot provide any guarantees on what the
function will do. Debug-time asserts are a middle ground solution, since
we can afford to perform more expensive checks in debug builds to
deterministically fail when preconditions are not met. That being said,
if the check is not prohibitively expensive, it should be performed on
all build flavors and immediately fail (via <code>std::terminate</code> or
equivalent).</p>

<p>What should not be done is treating such a state as an error - this is a
bug in the code and throwing an exception or returning some error result
would just leak the bug and make it impact more of the system. There
really isn't anything useful to do with such an error - it only tells
us that there is an issue in the code and we are now in a state we
should never be in. At this point we don't know which component
originated the error and we cannot deterministically recover - we might
abort the current operation but there is no guarantee that this would
bring us back to a valid state. We are in undefined behavior land, where
crashing is the best option.</p>

<h2>Recoverable Errors</h2>

<p>We covered several ways to handle errors by either eliminating invalid
states at compile-time or by failing fast when in an invalid state.
There are, on the other hand, classes of errors from which we can
legitimately recover, which brings us to exception and error codes.</p>

<h3>Exceptions</h3>

<p>I am a big fan of handling exceptional states using exceptions over
returning error codes. For one, the code is more readable: instead of
reserving the return type of a function to signal success or failure and
resort to out parameters, functions can be declared in a natural way. We
also end up with less code overall as instead of having to check error
codes inside all functions in the call stack in order to propagate back
an error, we simply throw it from the top of the stack and catch it
where we can deal with it. This approach also composes better - take,
for example, a generic algorithm that takes some throwing function.
Since we supply the predicate, we know what exception it can throw and
we can catch it in the code that invokes the generic algorithm, keeping
this invisible to the algorithm:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">InputIt</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">UnaryFunction</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">for_each</span><span class="p">(</span><span class="n">InputIt</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">InputIt</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">UnaryFunction</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="k">noexcept</span><span class="p">(</span><span class="k">noexcept</span><span class="p">(</span><span class="n">UnaryFunction</span><span class="p">))</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">first</span><span class="p">)</span>
<span class="w">        </span><span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>If our predicate returns an error code instead, the generic algorithm
must be aware of this:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">InputIt</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">UnaryFunction</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">for_each</span><span class="p">(</span><span class="n">InputIt</span><span class="w"> </span><span class="n">first</span><span class="p">,</span><span class="w"> </span><span class="n">InputIt</span><span class="w"> </span><span class="n">last</span><span class="p">,</span><span class="w"> </span><span class="n">UnaryFunction</span><span class="w"> </span><span class="n">f</span><span class="p">)</span><span class="w"> </span><span class="k">noexcept</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(;</span><span class="w"> </span><span class="n">first</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">last</span><span class="p">;</span><span class="w"> </span><span class="o">++</span><span class="n">first</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">auto</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">first</span><span class="p">);</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">result</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">result</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Note that here we are also making an assumption that 0 means success,
which is an arbitrary decision for a plug-in function.</p>

<p>That being said, I want to reiterate that exceptions should only be used
for exceptional cases. The readability advantage gained with exceptions
is lost if they are abused. It's great if the callee throws one or two
exception types which the caller catches and handles. On the other hand,
if we have to resort to catch-all <code>catch (...)</code> and we have so many
possible exception types coming out of a function that we can't keep
track of them, the code actually becomes harder to reason about.</p>

<p>An example and a counter-example: when reading a file with a set schema
generated by our application, we expect it to be in a valid format. If
it isn't, it means some data corruption occurred but this should really
be an exceptional case. If we encounter such data corruption, we can
throw an exception and let the caller handle the fact that we cannot
interpret this file. On the other hand, when reading user input, we
should never throw an exception if input is not conforming - this should
be a much more common scenario of user error.</p>

<h3>Return Codes</h3>

<p>There are cases which are not exceptional enough to warrant an exception
but where some error information needs to be propagated through the call
stack. Take, for example, a compiler which encounters an invalid token
while parsing a file. Since this is user input, it should not be treated
as an exception. On the other hand, simply using an optional and failing
to parse without providing additional information is also not ideal. In
this case we probably want to return additional information around the
encountered error.</p>

<p>In this case we would return the error rather than throw it, but I would
still prefer an embellished type like Rust's <code>Result</code> and return an
<code>std::variant&lt;T, Error&gt;</code> (as of C++17). In general I consider bad
practice returning an <code>int</code> or an <code>HRESULT</code> which would afterwards have
to be decoded to understand the actual error. For simple cases, if no
other information besides success/failure has to be returned, a <code>bool</code>
would suffice, or an <code>enum</code> or <code>struct</code> which contains the expected
error information. Such an error type can be composed with a valid
return type using a variant which brings us back to monadic
error-handling.</p>

<p>My general rule of thumb is to use exceptions for really exceptional
situations, which keeps the code cleaner as long as the number of
exception types is managable, and use monadic error handling when errors
are expected, as long as these can be scoped to a limited number of
functions (repeated error checking all over the place is messy,
error-prone, and makes code hard to read).</p>

<h2>Summary</h2>

<p>We went over various ways of handling errors:</p>

<ul>
<li>Declaring types that restrict the range of values a variable can
take to eliminate invalid states at compile-time.</li>
<li>Monadic error handling using embelished return types.</li>
<li>Failing fast when preconditions of a function are not met.</li>
<li>Throwing exceptions in exceptional cases.</li>
<li>Returning strongly typed errors when errors are not exceptional.</li>
</ul>

<p>There is still a fair amount of controversy around what is <em>the right
way</em> of handling errors. My personal take on this is that there are
tradeoffs that come with each approach and rather than saying <q>always
use exceptions</q> or <q>never use exceptions</q>, it's more a matter of
choosing <em>the right tool for the job</em>. I tried to list some of the
possible approaches with their pros and cons, and how I employ them.
Your mileage may vary depending on your specific language, runtime,
problem domain, application type etc.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>This is the recommended way of <a href="https://doc.rust-lang.org/book/error-handling.html">handling errors in
Rust</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>See Chandler Carruth's CppCon talk <a href="https://www.youtube.com/watch?v=yG1OZ69H_-o">Garbage In, Garbage
Out</a>. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sat, 03 Dec 2016 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/10/16/notes-on-types.html</link>
      <guid>https://vladris.com/blog/2016/10/16/notes-on-types.html</guid>
      <title><![CDATA[Notes on Types]]></title>
      <description><![CDATA[<h1>Notes on Types</h1>

<h2>Type Systems</h2>

<p>A good type system can eliminate entire categories of errors in a
program and simply make invalid code not compile. Before digging into
types, below are a few common distinctions between the type systems of
various programming languages:</p>

<h3>Dynamic Typing vs Static Typing</h3>

<p>In a statically typed language, the types are determined at compile time
so if a function was declared as only accepting a certain type <code>T</code> but
we attempt to pass it an unrelated type <code>U</code>, the program is considered
invalid. This is invalid C++:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">sqr</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="n">sqr</span><span class="p">(</span><span class="s">"not an int"</span><span class="p">);</span><span class="w"> </span><span class="c1">// does not compile</span>
</pre></div>

<p>On the other hand, in a dynamically typed language, we do not perform
any compile time checks and, if the data we get is of an unexpected
type, we treat it as a runtime error. Below is a Python function that
squares a number:</p>
<div class="highlight"><pre><span/><span class="k">def</span><span class="w"> </span><span class="nf">sqr</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">x</span> <span class="o">**</span> <span class="mi">2</span>
<span class="o">...</span>
<span class="n">sqr</span><span class="p">(</span><span class="s2">"not an int"</span><span class="p">)</span>
<span class="c1">## runs but fails with TypeError: unsupported operand type(s)</span>
<span class="c1">## for ** or pow(): 'str' and 'int'</span>
</pre></div>

<p>Some of the interesting features of dynamic languages are <em>duck typing</em>
(<q>if it walks like a duck, and it quacks like a duck...</q>) and <em>monkey
patching</em>. Duck typing means that accessing a member of an object works
as long as that object has such a member, regardless of the type of the
object. In Python:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Foo</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">print</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">)</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Bar</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">print</span><span class="p">(</span><span class="s2">"bar"</span><span class="p">)</span>

<span class="p">[</span><span class="n">obj</span><span class="o">.</span><span class="n">func</span><span class="p">()</span> <span class="k">for</span> <span class="n">obj</span> <span class="ow">in</span> <span class="p">[</span><span class="n">Foo</span><span class="p">(),</span> <span class="n">Bar</span><span class="p">()]]</span> <span class="c1"># prints "foo" and "bar"</span>
</pre></div>

<p>This can't work in a statically typed language where, at the bare
minimum, we would have to add some form of constraint for the types in
the list to ensure they contain a <code>func()</code> method we can call.</p>

<p>Monkey patching refers to the ability to change the structure of an
object at runtime. For example we can swap the <code>func</code> method from an
instance of <code>foo</code> with another function like this:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">Foo</span><span class="p">:</span>
    <span class="k">def</span><span class="w"> </span><span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="nb">print</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">)</span>

<span class="k">def</span><span class="w"> </span><span class="nf">func_bar</span><span class="p">():</span>
    <span class="nb">print</span><span class="p">(</span><span class="s2">"bar"</span><span class="p">)</span>

<span class="n">obj</span> <span class="o">=</span> <span class="n">Foo</span><span class="p">()</span>
<span class="n">obj</span><span class="o">.</span><span class="n">func</span><span class="p">()</span> <span class="c1"># prints "foo"</span>
<span class="n">obj</span><span class="o">.</span><span class="n">func</span> <span class="o">=</span> <span class="n">func_bar</span>
<span class="n">obj</span><span class="o">.</span><span class="n">func</span><span class="p">()</span> <span class="c1"># prints "bar"</span>
</pre></div>

<p>These are useful capabilities, but the tradeoff is a whole class of type
errors which a statically typed language would've caught.</p>

<p>As a side note, the fact that dynamic languages don't need to specify
types makes them more terse. That being said, the <a href="https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system">Hindley-Milner
algorithm
W</a> can
infer the types of a program in linear time with respect to the source
size. So while Python is starting to support type annotations for better
static analysis and TypeScript provides a way for writing type-safe
JavaScript, C++ has better and better type inference, while in Haskell
(which has one of the strongest static type systems) type annotations
are mostly optional.</p>

<h3>Strong Typing vs Weak Typing</h3>

<p>At a high level, a strongly typed language does not implicitly convert
between unrelated types. This is good in most situations as implicit
conversions are often meaningless or have surprising effects - for
example, adding a number to a list of characters. This can either result
in runtime errors or garbage data. In contrast, a strongly typed
language will not accept code that attempts to do this.</p>

<p>In Python, which is strongly typed, this doesn't work:</p>
<div class="highlight"><pre><span/><span class="n">foo</span> <span class="o">=</span> <span class="s2">"foo"</span> <span class="c1"># foo is "foo"</span>
<span class="n">foo</span> <span class="o">=</span> <span class="n">foo</span> <span class="o">+</span> <span class="s2">" bar"</span> <span class="c1"># foo is "foo bar"</span>
<span class="n">foo</span> <span class="o">=</span> <span class="n">foo</span> <span class="o">+</span> <span class="mi">5</span> <span class="c1"># TypeError: Can't convert 'int' object to str implicitly</span>
</pre></div>

<p>It works just fine in JavaScript though:</p>
<div class="highlight"><pre><span/><span class="kd">var</span><span class="w"> </span><span class="nx">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s2">"foo"</span><span class="p">;</span><span class="w"> </span><span class="c1">// foo is "foo"</span>
<span class="nx">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">foo</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s2">" bar"</span><span class="p">;</span><span class="w"> </span><span class="c1">// foo is "foo bar"</span>
<span class="nx">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">foo</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mf">5</span><span class="p">;</span><span class="w"> </span><span class="c1">// foo is "foo bar5"</span>
</pre></div>

<p>Note type strength is not an either/or - C++, while considered strongly
typed, still allows several implicit casts between types (eg. pointer to
bool). Some languages are more strict about converting between types
implicitly, others less so.</p>

<h3>Dynamic Polymorphism vs Static Polymorphism</h3>

<p>Another difference to note is between static and dynamic polymorphism.
Dynamic polymorphism happens at runtime, when calling a function on a
base type gets resolved to the actual function of the deriving type:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">base</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">func</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">foo</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">base</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">func</span><span class="p">()</span><span class="w"> </span><span class="k">override</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">"foo"</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">bar</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">base</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">func</span><span class="p">()</span><span class="w"> </span><span class="k">override</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">"bar"</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">call_func</span><span class="p">(</span><span class="n">base</span><span class="o">&amp;</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">obj</span><span class="p">.</span><span class="n">func</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="n">call_func</span><span class="p">(</span><span class="n">foo</span><span class="p">{});</span><span class="w"> </span><span class="c1">// prints "foo"</span>
<span class="n">call_func</span><span class="p">(</span><span class="n">bar</span><span class="p">{});</span><span class="w"> </span><span class="c1">// prints "bar"</span>
</pre></div>

<p>In the above case, we effectively have a single function <code>call_func</code>
which takes a reference to a <code>base</code> struct. The compiler generates a
v-table for <code>struct base</code> and a call to <code>func()</code> on <code>base</code> involves a
v-table jump to the actual implementation of the function, which is
different between the inheriting types <code>foo</code> and <code>bar</code>.</p>

<p>Contrast this with the static alternative:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">foo</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">func</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">"foo"</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">bar</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">func</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">"bar"</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">endl</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="n">call_func</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">obj</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">obj</span><span class="p">.</span><span class="n">func</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="n">call_func</span><span class="p">(</span><span class="n">foo</span><span class="p">{});</span><span class="w"> </span><span class="c1">// prints "foo"</span>
<span class="n">call_func</span><span class="p">(</span><span class="n">bar</span><span class="p">{});</span><span class="w"> </span><span class="c1">// prints "bar"</span>
</pre></div>

<p>In this case there is no relationship between <code>foo</code> and <code>bar</code> and no
v-table is needed. On the other hand, we no longer have a single
<code>call_func</code>, we have a templated function which is instantiated for both
<code>foo</code> and <code>bar</code> types. This is all done at compile-time, the advantage
being faster code, the drawback being compiler needs to be aware of all
the types involved - we can no longer <q>inject</q> types implementing an
interface at runtime. When calling <code>call_func</code>, we need to have both the
definition of the function and the declaration of the type we're
passing in visible.</p>

<h2>Types</h2>

<p>During the rest of this post, I will talk about types in the context of
a statically and strongly typed language, with a focus on static
polymorphism. This pushes as much as possible of the type checking to
the compilation stage, so many of the runtime issues of less strict
languages become invalid syntax.</p>

<p>I will focus on C++ and cover some of the new C++17 feature which enable
or make some of these concepts easier to work with. That being said,
since this post focuses on types, I will also provide examples in
Haskell, as Haskell can express these concepts much more succinctly.</p>

<h3>Type Basics</h3>

<p>Let's start with the definition of a type: <em>a type represents the set
of possible values</em>. For example, the C++ type <code>uint8_t</code> represents the
set of integers from 0 to 255. Effectively this means that a variable of
a given type can only have values from within that set.</p>

<h3>Interesting Types</h3>

<p>Since we defined a type as a set of possible values, we can talk about
the cardinality of a type, in other words the number of values in the
set. Based on cardinality, there are a few interesting classes of types
to talk about:</p>

<h3>Empty Type</h3>

<p>The first interesting type to talk about is the type that represents the
empty set, with <code>|T| = 0</code>.</p>

<p>In Haskell, this type is named <code>Void</code>. Since Haskell is a functional
language, all functions must return a value, so it does not make sense
to have a function that returns <code>Void</code> - the same way it doesn't make
sense to define a mathematical function with the empty set as its
codomain. We do have an <code>absurd</code> function though, which maps the empty
set to any value:</p>
<div class="highlight"><pre><span/><span class="nf">absurd</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Void</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">a</span>
</pre></div>

<p>This function cannot be called though.</p>

<p>In C++, the absence of a value is represented as the <code>void</code> type. Since
C++ is not purely functional, we can define functions that don't return
anything. We can even say that a function does not take any arguments by
putting a <code>void</code> between the parenthesis:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="kt">void</span><span class="p">);</span>
</pre></div>

<p>This is the equivalent of:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">();</span>
</pre></div>

<p>Note though that we cannot have a <em>real</em> argument of type <code>void</code>, that
is a compile error as it doesn't make any sense - we would be mandating
the function takes a value from the empty set. So we can say <code>foo(void)</code>
but not <code>foo(void arg)</code>, or even <code>foo(int arg, void)</code>.</p>

<h3>Unit Type</h3>

<p>The next interesting class consists of types with cardinality 1. A type
<code>T</code> with <code>|T| = 1</code> is called a <em>unit</em> or <em>singleton type</em>. A variable of
such a type can only ever have a single possible value. In Haskell, the
anonymous representation is the empty tuple <code>()</code>. Here is an example of
a function that maps anything to this type:</p>
<div class="highlight"><pre><span/><span class="nf">unit</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="nb">()</span>
<span class="nf">unit</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="nb">()</span>
</pre></div>

<p>Of course, we can declare our own singleton types. Below is a custom
<code>Singleton</code> type and an equivalent unit function:</p>
<div class="highlight"><pre><span/><span class="kr">data</span><span class="w"> </span><span class="kt">Singleton</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Singleton</span>
<span class="nf">unit</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Singleton</span>
<span class="nf">unit</span><span class="w"> </span><span class="kr">_</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Singleton</span>
</pre></div>

<p>In C++, the anonymous representation of a singleton is an empty
<code>std::tuple</code>:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;&gt;</span><span class="w"> </span><span class="n">unit</span><span class="p">(</span><span class="n">T</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<p>As can be seen from the above, Haskell makes it easier to define a
function that takes an argument of any type, as it provides syntactic
sugar for type parameters (<code>a</code> in our example). In C++, the equivalent
declaration involves a template, but they boil down to the same thing.
The non-anonymous C++ representation is a struct which doesn't contain
anything. All instances of such a struct are equivalent:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">singleton</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">singleton</span><span class="w"> </span><span class="n">unit</span><span class="p">(</span><span class="n">T</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">};</span>
<span class="p">}</span>
</pre></div>

<h3>Sum Types</h3>

<p>Here, things get a bit more interesting: a <code>sum type</code> is a type which
can represent a value from any of the types it sums. So given type <code>A</code>
and type <code>B</code>, the type <code>S</code> summing up <code>A</code> and <code>B</code> is
<code>S = { i : i â A U B }</code>. So a variable of type <code>S</code> could have any value
in <code>A</code> or any value in <code>B</code>. <code>S</code> is called a sum type because its
cardinality is the sum of the cardinalities of <code>A</code> and <code>B</code>,
<code>|S| = |A| + |B|</code>.</p>

<p>Sum types are great, because they allow us to build up more complex
types from simpler ones. Once we have unit types, we can build up more
complex types out of them by summing them. For example, a boolean type
which can be either <code>true</code> or <code>false</code> can be thought of as the sum of
the singleton <code>true</code> type and the singleton <code>false</code> type. In Haskell, a
boolean is defined as:</p>
<div class="highlight"><pre><span/><span class="kr">data</span><span class="w"> </span><span class="kt">Bool</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">True</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">False</span>
</pre></div>

<p>Similarly, a <code>Weekday</code> type can be defined as:</p>
<div class="highlight"><pre><span/><span class="kr">data</span><span class="w"> </span><span class="kt">Weekday</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Monday</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Tuesday</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Wednesday</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Thursday</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Friday</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Saturday</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Sunday</span>
</pre></div>

<p>Theoretically, numerical types could also be defined as huge sum types
of every possible value they can represent. Of course, this is
impractical, but we can reason about them the same way we reason about
other sum types, we don't have to treat them as a special case.</p>

<p>In C++, an equivalent of the above is an <code>enum class</code>. <code>bool</code> is a
built-in type with special syntax, but we could define an equivalent as:</p>
<div class="highlight"><pre><span/><span class="k">enum</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Boolean</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">True</span><span class="p">,</span>
<span class="w">    </span><span class="n">False</span>
<span class="p">};</span>
</pre></div>

<p>It's easy to see how a <code>Weekday</code> definition would look like. Things get
more interesting when we throw type parameters into the mix. In Haskell,
we have the <code>Either</code> type, which is declared as follows:</p>
<div class="highlight"><pre><span/><span class="kr">data</span><span class="w"> </span><span class="kt">Either</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Left</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Right</span><span class="w"> </span><span class="n">b</span>
</pre></div>

<p>An instance of this could be either a <code>Left a</code>, where <code>a</code> is a type
itself, which means it can be any of the values of <code>a</code>, or it can be
<code>Right b</code>, with any of the values of <code>b</code>. In Haskell we use
pattern-matching to operate on such a type, so we can declare a simple
function that tells us whether we were given a <code>Left a</code> like this:</p>
<div class="highlight"><pre><span/><span class="nf">isLeft</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Either</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Bool</span>
<span class="nf">isLeft</span><span class="w"> </span><span class="p">(</span><span class="kt">Left</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">True</span>
<span class="nf">isLeft</span><span class="w"> </span><span class="p">(</span><span class="kt">Right</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">False</span>
</pre></div>

<p>This might not look like much, but of course we can compose more complex
functions. For example, say we have a function <code>foo</code> that takes an <code>a</code>
and returns an <code>a</code>, a function <code>bar</code> that takes a <code>b</code> and returns a <code>b</code>.
We can then write a <code>transform</code> function which takes an <code>Either a b</code>
and, depending on the contained type, it applies the appropriate
function:</p>
<div class="highlight"><pre><span/><span class="c1">-- Implementation of foo and bar not provided in this example</span>
<span class="nf">foo</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">a</span>
<span class="nf">bar</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">b</span>

<span class="nf">transform</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Either</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Either</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="n">b</span>
<span class="nf">transform</span><span class="w"> </span><span class="p">(</span><span class="kt">Left</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Left</span><span class="w"> </span><span class="p">(</span><span class="n">foo</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="nf">transform</span><span class="w"> </span><span class="p">(</span><span class="kt">Right</span><span class="w"> </span><span class="n">b</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Right</span><span class="w"> </span><span class="p">(</span><span class="n">bar</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
</pre></div>

<p>This is way beyond the capabilities of a C++ <code>enum class</code>. The old way
of implementing something like this in C++ was using a union and a tag
enum to keep track of which is the actual type we're working with:</p>
<div class="highlight"><pre><span/><span class="c1">// Declaration of A and B not provided in this example</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">A</span><span class="p">;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">B</span><span class="p">;</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">Either</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Either</span><span class="p">(</span><span class="n">A</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">ab</span><span class="p">.</span><span class="n">left</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">a</span><span class="p">;</span>
<span class="w">        </span><span class="n">tag</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tag</span><span class="o">::</span><span class="n">isA</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">Either</span><span class="p">(</span><span class="n">B</span><span class="w"> </span><span class="n">b</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">ab</span><span class="p">.</span><span class="n">right</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">b</span><span class="p">;</span>
<span class="w">        </span><span class="n">tag</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tag</span><span class="o">::</span><span class="n">isB</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">union</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">A</span><span class="w"> </span><span class="n">left</span><span class="p">;</span>
<span class="w">        </span><span class="n">B</span><span class="w"> </span><span class="n">right</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="n">ab</span><span class="p">;</span>

<span class="w">    </span><span class="k">enum</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">tag</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">isA</span><span class="p">,</span>
<span class="w">        </span><span class="n">isB</span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="n">tag</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Our implementation of transform would look like this:</p>
<div class="highlight"><pre><span/><span class="c1">// Implementation of A and B not provided in this example</span>
<span class="n">A</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">A</span><span class="p">);</span>
<span class="n">B</span><span class="w"> </span><span class="nf">bar</span><span class="p">(</span><span class="n">B</span><span class="p">);</span>

<span class="n">Either</span><span class="w"> </span><span class="nf">transform</span><span class="p">(</span><span class="n">Either</span><span class="w"> </span><span class="n">either</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">switch</span><span class="w"> </span><span class="p">(</span><span class="n">either</span><span class="p">.</span><span class="n">tag</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="no">Either</span><span class="o">::</span><span class="no">tag</span><span class="o">::</span><span class="no">isA</span><span class="p">:</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">foo</span><span class="p">(</span><span class="n">either</span><span class="p">.</span><span class="n">ab</span><span class="p">.</span><span class="n">left</span><span class="p">);</span>
<span class="w">        </span><span class="k">case</span><span class="w"> </span><span class="no">Either</span><span class="o">::</span><span class="no">tag</span><span class="o">::</span><span class="no">isB</span><span class="p">:</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">bar</span><span class="p">(</span><span class="n">either</span><span class="p">.</span><span class="n">ab</span><span class="p">.</span><span class="n">right</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Our <code>Either</code> type definition is obviously much more verbose than what we
had in Haskell, and it doesn't even support type parameters - at this
point it only works with <code>struct A</code> and <code>struct B</code>, while the Haskell
version works for any <code>a</code> and <code>b</code> types. The other major problem is
that, while unions provide efficient storage for different types (the
size of the union is the size of the maximum contained type), it is up
to the implementer to make sure we don't try to read an <code>A</code> as a <code>B</code> or
vice-versa. That means we need to keep our tag in sync with what we put
in the type and respect it when accessing the value of the union.</p>

<p>C++17 introduces a better, safer, parameterized type for this:
<code>std::variant</code>. Variant takes any number of types as template arguments
and stores an instance of any one of those types. Using variant, we can
re-write the above as:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">variant</span><span class="o">&lt;</span><span class="n">A</span><span class="p">,</span><span class="w"> </span><span class="n">B</span><span class="o">&gt;</span><span class="w"> </span><span class="n">transform</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">variant</span><span class="o">&lt;</span><span class="n">A</span><span class="p">,</span><span class="w"> </span><span class="n">B</span><span class="o">&gt;</span><span class="w"> </span><span class="n">either</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">visit</span><span class="p">([](</span><span class="k">auto</span><span class="w"> </span><span class="n">e</span><span class="o">&amp;&amp;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="k">constexpr</span><span class="w"> </span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">is_same_v</span><span class="o">&lt;</span><span class="k">decltype</span><span class="p">(</span><span class="n">e</span><span class="p">),</span><span class="w"> </span><span class="n">A</span><span class="o">&gt;</span><span class="p">)</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">foo</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span><span class="p">(</span><span class="n">e</span><span class="p">));</span>
<span class="w">        </span><span class="k">else</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">bar</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="n">B</span><span class="o">&gt;</span><span class="p">(</span><span class="n">e</span><span class="p">));</span>
<span class="w">    </span><span class="p">},</span><span class="w"> </span><span class="n">either</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>This is a lot of new syntax, so let's break it down:
<code>std::variant&lt;A, B&gt;</code> is the new C++17 sum type. In this case, we specify
it holds either <code>A</code> or <code>B</code> (but it can hold an arbitrary number of
types).</p>

<p><code>std::visit</code> is a function that applies the visitor function given as
its first argument to the variants given as its subsequent arguments. In
our example, this effectively expands to applying the lambda to
<code>std::get&lt;0&gt;(either)</code> and <code>std::get&lt;1&gt;(either)</code>.</p>

<p><code>if constexpr</code> is also a new C++17 construct which evaluates the if
expression at compile time and discards the else branch from the final
object code. So in this example, we determine at compile time whether
the type we are being called with is <code>A</code> or <code>B</code> and apply the correct
function based on that. Something very similar can be achieved with
templates and <code>enable_if</code>, but this syntax makes for more readable code.</p>

<p>Note that with this version we can simply prepend a
<code>template &lt;typename A, typename B&gt;</code> and make the whole function generic,
as in the Haskell example. It doesn't read as pretty (because we don't
have good pattern matching syntax in the language), but this is the new,
type safe way of implementing and working with sum types, which is a
major improvement.</p>

<h3>Product Types</h3>

<p>With sum types out of the way, the remaining interesting category is
that of <em>product types</em>. Product types combine the values of several
other types into one. For types <code>A</code> and <code>B</code>, we have
<code>P = { (a, b) : a â A, b â B }</code>, so <code>|P| = |A| x |B|</code>.</p>

<p>In Haskell, the anonymous version of product types is represented by
tuples, while the named version is represented by records. An example of
a <code>perimeter</code> function which computes the perimeter of a rectangle
defined by two points, where each point is a tuple of numbers:</p>
<div class="highlight"><pre><span/><span class="nf">perimeter</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="p">(</span><span class="kt">Num</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="ow">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">n</span>
<span class="nf">perimeter</span><span class="w"> </span><span class="p">(</span><span class="n">x1</span><span class="p">,</span><span class="w"> </span><span class="n">y1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="n">x2</span><span class="p">,</span><span class="w"> </span><span class="n">y2</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">x1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">x2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">abs</span><span class="p">(</span><span class="n">y1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">y2</span><span class="p">))</span>
</pre></div>

<p>The named version would declare a <code>Point</code> type with <code>Int</code> coordinates
and use that instead:</p>
<div class="highlight"><pre><span/><span class="kr">data</span><span class="w"> </span><span class="kt">Point</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Point</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Int</span><span class="w"> </span><span class="p">}</span>

<span class="nf">perimeter</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Point</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Point</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Int</span>
<span class="nf">perimeter</span><span class="w"> </span><span class="p">(</span><span class="kt">Point</span><span class="w"> </span><span class="n">x1</span><span class="w"> </span><span class="n">y1</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="kt">Point</span><span class="w"> </span><span class="n">x2</span><span class="w"> </span><span class="n">y2</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">x1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">x2</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">abs</span><span class="p">(</span><span class="n">y1</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">y2</span><span class="p">))</span>
</pre></div>

<p>The C++ equivalents are <code>std::tuple</code> for anonymous product types and
<code>struct</code> for named types:</p>
<div class="highlight"><pre><span/><span class="c1">// Anonymous</span>
<span class="kt">int</span><span class="w"> </span><span class="nf">perimeter</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">p1</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">tuple</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">p2</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">((</span><span class="n">abs</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">0</span><span class="o">&gt;</span><span class="p">(</span><span class="n">p2</span><span class="p">))</span>
<span class="w">        </span><span class="o">+</span><span class="w"> </span><span class="n">abs</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">p1</span><span class="p">)</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">get</span><span class="o">&lt;</span><span class="mi">1</span><span class="o">&gt;</span><span class="p">(</span><span class="n">p2</span><span class="p">)));</span>
<span class="p">}</span>

<span class="c1">// Named</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">point</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">;</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">y</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">int</span><span class="w"> </span><span class="nf">perimeter</span><span class="p">(</span><span class="n">point</span><span class="w"> </span><span class="n">p1</span><span class="p">,</span><span class="w"> </span><span class="n">point</span><span class="w"> </span><span class="n">p2</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="p">(</span><span class="n">abs</span><span class="p">(</span><span class="n">p1</span><span class="p">.</span><span class="n">x</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">abs</span><span class="p">(</span><span class="n">p1</span><span class="p">.</span><span class="n">y</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">p2</span><span class="p">.</span><span class="n">y</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>While sum types allow us to express values from multiple types into one,
product types allow us to express values from several types together.
Empty, unit, sum, and product types are the building blocks of a type
system.</p>

<h3>Bonus: Optional Types</h3>

<p>An optional type is a type that can hold any of the values of another
type, or not hold any value, which is usually represented as a
singleton. So an optional is effectively a sum type between a given type
and a singleton representing <q>doesn't hold a value</q>. In other words,
the cardinality of an optional for a type <code>T</code> is <code>|O| = |T| + 1</code>.</p>

<p>In Haskell, an optional is the famous <code>Maybe</code> type:</p>
<div class="highlight"><pre><span/><span class="kr">data</span><span class="w"> </span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="kt">Nothing</span>
</pre></div>

<p>A function that operates on <code>Maybe</code> could say <q>only apply <code>foo</code> if the
optional contains an <code>a</code></q>:</p>
<div class="highlight"><pre><span/><span class="c1">-- Implementation of foo not provided in this example</span>
<span class="nf">foo</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="n">a</span>

<span class="nf">transform</span><span class="w"> </span><span class="ow">::</span><span class="w"> </span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="ow">-&gt;</span><span class="w"> </span><span class="kt">Maybe</span><span class="w"> </span><span class="n">a</span>
<span class="nf">transform</span><span class="w"> </span><span class="p">(</span><span class="kt">Just</span><span class="w"> </span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Just</span><span class="w"> </span><span class="p">(</span><span class="n">foo</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="nf">transform</span><span class="w"> </span><span class="kt">Nothing</span><span class="w"> </span><span class="ow">=</span><span class="w"> </span><span class="kt">Nothing</span>
</pre></div>

<p>The new C++17 equivalent is the <code>optional</code> type:</p>
<div class="highlight"><pre><span/><span class="c1">// Implementation of foo not provided in this example</span>
<span class="n">A</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">A</span><span class="p">);</span>

<span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span><span class="w"> </span><span class="n">transform</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">optional</span><span class="o">&lt;</span><span class="n">A</span><span class="o">&gt;</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">nullopt</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="n">foo</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">nullopt</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This might read a bit like the pointer implementation:</p>
<div class="highlight"><pre><span/><span class="n">A</span><span class="o">*</span><span class="w"> </span><span class="nf">transform</span><span class="p">(</span><span class="n">A</span><span class="o">*</span><span class="w"> </span><span class="n">a</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">a</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="nb">nullptr</span><span class="w"> </span><span class="o">?</span><span class="w"> </span><span class="n">foo</span><span class="p">(</span><span class="o">*</span><span class="n">a</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="nb">nullptr</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>There is a key difference though: the type contained in the optional is
part of the object, so it is not allocated dynamically the way we would
allocate a pointer. <code>nullopt</code> is a helper object of the singleton type
<code>nullopt_t</code>.</p>

<p>Types are important because a big part of programming effectively
consits of designing and composing types. Having a good understanding of
the fundamentals leads to better, safer, and saner code.</p>

<h2>Summary</h2>

<p>We started by outlining some of the basic principles of type systems:</p>

<ul>
<li>Static and dynamic typing.</li>
<li>Weak and strong typing.</li>
<li>Static and dynamic polymorphism.</li>
</ul>

<p>Then we went over the building block types of a type system, with
Haskell and C++ examples:</p>

<ul>
<li>Empty types (cardinality 0).</li>
<li>Unit types (cardinality 1).</li>
<li>Sum types (<code>S</code> of <code>A</code> and <code>B</code> has cardinality <code>A + B</code>).</li>
<li>Product types (<code>P</code> of <code>A</code> and <code>B</code> has cardinality <code>A x B</code>).</li>
<li>Optional types (<code>O</code> of <code>A</code> has cardinality <code>A + 1</code>).</li>
</ul>

<h2>Further Reading</h2>

<p>Ben Dean had an excellent talk at CppCon this year, <a href="https://www.youtube.com/watch?v=ojZbFIQSdl8">Using Types
Effectively</a>. Another great
talk about type design from CppCon is <a href="https://www.youtube.com/watch?v=632a-DMM5J0">C++, Abstract Algebra and
Practical Applications</a> by
Robert Ramey. And then there is Bartosz Milewski
<a href="https://bartoszmilewski.com/">blog</a> about Haskell, C++, and category
theory.</p>
]]></description>
      <pubDate>Sun, 16 Oct 2016 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/10/09/composable-generators.html</link>
      <guid>https://vladris.com/blog/2016/10/09/composable-generators.html</guid>
      <title><![CDATA[Composable Generators]]></title>
      <description><![CDATA[<h1>Composable Generators</h1>

<p>One of the most exciting features coming to C++ are coroutines. In this
post, I will give a quick overview of how they are used today in C# to
support generators and go over a few possible ways to bring the
composability of Linq to the C++ world.</p>

<h2>Generators in C</h2>

<p>I will not go into the nitty-gritty details of coroutines, but in short,
they are resumable functions -- functions that can be suspended/resumed.
Coroutines enable lazy evaluation, with two major applications: easy to
read multi-threading (with async/await syntax in C#) and generators
(with yield return syntax in C#). In this post, I will focus on
generators and how they compose.</p>

<p>I will start with a C# example since Linq is, in my opinion, the golden
standard for creating a processing pipeline, at least for non-functional
languages. Linq is implemented as a set of extension methods for
<code>IEnumerable</code>, and enables some very readable chaining of operations.
For example, let's get the first 100 natural numbers, filter out the
odds, then square the remaining list.</p>

<p>The wrong way of doing this would be something like:</p>
<div class="highlight"><pre><span/><span class="k">static</span><span class="w"> </span><span class="n">IEnumerable</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">GetNumbers</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">100</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">            </span><span class="k">yield</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">var</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">GetNumbers</span><span class="p">();</span>

<span class="w">    </span><span class="k">foreach</span><span class="w"> </span><span class="p">(</span><span class="kt">var</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">result</span><span class="p">)</span>
<span class="w">        </span><span class="n">Console</span><span class="p">.</span><span class="n">Write</span><span class="p">(</span><span class="n">item</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">" "</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>The main problem with the above is that all the logic is inlined into
<code>GetNumbers</code>, so things don't decompose very well -- for example what if
we also want a function that squares the odd numbers? We would either
duplicate the looping and squaring logic, or make the predicate we use
to filter out things an input to the function. Same goes for the
iterating logic and for the squaring. Luckily, we have Linq, which does
just that:</p>
<div class="highlight"><pre><span/><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">var</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span>
<span class="w">        </span><span class="n">Enumerable</span><span class="p">.</span><span class="n">Range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="mi">100</span><span class="p">).</span>
<span class="w">        </span><span class="n">Where</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">).</span>
<span class="w">        </span><span class="n">Select</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">);</span>

<span class="w">    </span><span class="k">foreach</span><span class="w"> </span><span class="p">(</span><span class="kt">var</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">result</span><span class="p">)</span>
<span class="w">        </span><span class="n">Console</span><span class="p">.</span><span class="n">Write</span><span class="p">(</span><span class="n">item</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">" "</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>To illustrate the magic of generators, instead of relying on
<code>Enumerable.Range</code>, let's introduce a function that generates numbers
forever:</p>
<div class="highlight"><pre><span/><span class="k">static</span><span class="w"> </span><span class="n">IEnumerable</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">Count</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="w">        </span><span class="k">yield</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Our code would then become:</p>
<div class="highlight"><pre><span/><span class="k">static</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Main</span><span class="p">(</span><span class="kt">string</span><span class="p">[]</span><span class="w"> </span><span class="n">args</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">var</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span>
<span class="w">        </span><span class="n">Count</span><span class="p">().</span>
<span class="w">        </span><span class="n">Take</span><span class="p">(</span><span class="mi">100</span><span class="p">).</span>
<span class="w">        </span><span class="n">Where</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">).</span>
<span class="w">        </span><span class="n">Select</span><span class="p">(</span><span class="n">x</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">);</span>

<span class="w">    </span><span class="k">foreach</span><span class="w"> </span><span class="p">(</span><span class="kt">var</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">result</span><span class="p">)</span>
<span class="w">        </span><span class="n">Console</span><span class="p">.</span><span class="n">Write</span><span class="p">(</span><span class="n">item</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">" "</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>While not strictly necessary in this particular case, infinite
generators cannot exist without lazy evaluation, a feature of many
functional languages. Lazy evaluation has some very practical
applications as it allows processing of data as it becomes available,
instead of waiting for everything to be ready before moving on to the
next step. While the 100 natural numbers example might not sound so
useful, imagine rendering frames in a streaming video as they arrive
over the network. Linq is great because it provides a clean separation
between the generic algorithms (<code>Where</code>, <code>Select</code> etc.) and the
problem-specific operations which are passed in as arguments. Linq
operations also compose well, so they can be chained together to form
pipelines.</p>

<h2>Generators in C++</h2>

<p>While coroutines haven't made it into the C++17 standard itself, they
are coming as a technical specification, with MSVC already supporting
them (code samples below compile with VS 2015 Update 3). The main syntax
additions are the new <code>co_await</code>, <code>co_return</code>, and <code>co_yield</code> keywords.
The first two are used for creating and awaiting tasks (which I won't
cover in this post), while <code>co_yield</code> is used in generators.</p>

<p>Here is a lazy counter in C++:</p>
<div class="highlight"><pre><span/><span class="k">auto</span><span class="w"> </span><span class="n">count_to</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">n</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="w">        </span><span class="k">co_yield</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">int</span><span class="w"> </span><span class="n">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">count_to</span><span class="p">(</span><span class="mi">100</span><span class="p">))</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">" "</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Note the return type of <code>count_to</code> is a <code>generator&lt;int&gt;</code> (currently in
the experimental namespace). <code>generator&lt;T&gt;</code> is the type implicitly
created by the compiler when encountering a <code>co_yield</code>. Also worth
noting that range-based for loops work over generators, as they expose
<code>begin()</code> and <code>end()</code> methods. The type annotation for the <code>count_to</code>
return type above is not really needed, I added it just to clarify what
the complier will generate in this case.</p>

<p><code>generator</code> itself is pretty bare-boned, it doesn't provide all the
algorithms that Linq adds to <code>IEnumerable</code>. So if we wanted to do
something like the above pipeline, we would need some algorithms. Here's
one way of implementing some of them:</p>
<div class="highlight"><pre><span/><span class="k">auto</span><span class="w"> </span><span class="n">count</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">100</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="w">        </span><span class="k">co_yield</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">take_n</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="o">++</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="w">            </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">        </span><span class="k">else</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">filter</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="n">Predicate</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pred</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>
<span class="w">            </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">BinaryOperation</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">map</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="n">BinaryOperation</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">co_yield</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Here I switched from Linq's <code>Select</code> and <code>Where</code> to the more commonly
used <code>map</code> and <code>filter</code>, but they effectively implement the same thing.
While this implementation is pretty-straight forward, it doesn't compose
well at all:</p>
<div class="highlight"><pre><span/><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span>
<span class="w">        </span><span class="n">map</span><span class="p">(</span>
<span class="w">            </span><span class="n">filter</span><span class="p">(</span>
<span class="w">                </span><span class="n">take_n</span><span class="p">(</span><span class="n">count</span><span class="p">(),</span><span class="w"> </span><span class="mi">100</span><span class="p">),</span>
<span class="w">                </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">){</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">}),</span>
<span class="w">            </span><span class="p">[](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">){</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">;});</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">result</span><span class="p">)</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">" "</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Definitely not like the nice chaining of Linq. So what gives? Why
doesn't generator come out-of-the-box with <code>take_n</code>, <code>map</code>, <code>filter</code> and
all the other useful algorithms? Well, according to the <a href="https://en.wikipedia.org/wiki/Single_responsibility_principle">single
responsibility
principle</a>,
these algorithms don't belong in <code>generator</code> -- <code>generator</code> encapsulates
the lazy evaluation of the coroutine, it wouldn't be the right place for
algorithms. It's also worth noting that Linq methods are not part of
<code>IEnumerable</code>, they are <a href="https://msdn.microsoft.com/en-us/library/bb383977.aspx">extension
methods</a>. C++
doesn't support extension methods, so we would need a slightly different
design to achieve better chaining.</p>

<h2>Decorator</h2>

<p>The next idea comes from pure OOP - let's create a decorator over
<code>generator</code> that exposes these algorithms. First, let's declare our
decorator as <code>enumerable&lt;T&gt;</code> and change our algorithms to work with the
new type:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">enumerable</span><span class="p">;</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">take_n</span><span class="p">(</span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="o">++</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="w">            </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">        </span><span class="k">else</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">filter</span><span class="p">(</span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="n">Predicate</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pred</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>
<span class="w">            </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">BinaryOperation</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">map</span><span class="p">(</span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="n">BinaryOperation</span><span class="w"> </span><span class="n">op</span><span class="p">)</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">co_yield</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>The implementation looks pretty much like before, except that now we are
getting and returning <code>enumerable&lt;T&gt;</code> instead of <code>generator&lt;T&gt;</code>. In this
case the type annotation is mandatory, as by default the complier would
create a <code>generator&lt;T&gt;</code>.</p>

<p>We can then implement our enumerable to wrap a generator and expose
member functions which forward to the above algorithms:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">enumerable</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// Needed by compiler to create enumerable from co_yield</span>
<span class="w">    </span><span class="k">using</span><span class="w"> </span><span class="n">promise_type</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;::</span><span class="n">promise_type</span><span class="p">;</span>

<span class="w">    </span><span class="n">enumerable</span><span class="p">(</span><span class="n">promise_type</span><span class="o">&amp;</span><span class="w"> </span><span class="n">promise</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">_gen</span><span class="p">(</span><span class="n">promise</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="n">enumerable</span><span class="p">(</span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">other</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">_gen</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">_gen</span><span class="p">))</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="n">enumerable</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;&amp;</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">delete</span><span class="p">;</span>
<span class="w">    </span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="o">&amp;</span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="o">&amp;</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">delete</span><span class="p">;</span>

<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">_gen</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">end</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">_gen</span><span class="p">.</span><span class="n">end</span><span class="p">();</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">take_n</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">::</span><span class="n">take_n</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">),</span><span class="w"> </span><span class="n">n</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">filter</span><span class="p">(</span><span class="n">Predicate</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">::</span><span class="n">filter</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">),</span><span class="w"> </span><span class="n">pred</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">BinaryOperation</span><span class="o">&gt;</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">map</span><span class="p">(</span><span class="n">BinaryOperation</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="o">::</span><span class="n">map</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">),</span><span class="w"> </span><span class="n">op</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">_gen</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>A few things to note: we declare a <code>promise_type</code> and have a constructor
which takes a promise as an argument. This is required by the compiler
when creating the object on <code>co_yield</code>. We follow the same semantics as
generator, since that is what we are wrapping -- support only
move-constructor, no copy-constructor. All the member algorithms do a
destructive move on <code>*this</code>. This is intentional, as once we iterate
over the encapsulated generator, it is no longer valid. Since we don't
expose a copy-constructor, we move out of <code>*this</code> when passing the
generator to an algorithm. For completeness, we can also provide a
function which converts from a generator to an enumerable:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">to_enumerable</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span><span class="w"> </span><span class="o">-&gt;</span><span class="w"> </span><span class="n">enumerable</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>This works, and we can now compose algorithms by chaining the calls:</p>
<div class="highlight"><pre><span/><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span>
<span class="w">        </span><span class="n">to_enumerable</span><span class="p">(</span><span class="n">count</span><span class="p">()).</span>
<span class="w">        </span><span class="n">take_n</span><span class="p">(</span><span class="mi">100</span><span class="p">).</span>
<span class="w">        </span><span class="n">filter</span><span class="p">([](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">}).</span>
<span class="w">        </span><span class="n">map</span><span class="p">([](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">result</span><span class="p">)</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">" "</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>Still, it is not ideal -- first, we need to explicitly tell the compiler
everywhere to return our type with <code>co_yield</code> instead of the default
generator, and we need to handle conversions to and from the standard
library generator. The enumerable algorithms compose well, but we'll
have trouble composing with functions that work with generators. Also,
having a huge class consisting solely of algorithms is not the best
design, especially in a language where free functions are first class
citizens.</p>

<h2>Pipe Operator</h2>

<p>An alternative approach, which the <a href="http://www.boost.org/doc/libs/1_62_0/libs/range/doc/html/index.html">Boost Ranges
library</a>
takes, is to overload <code>|</code>, the <q>pipe</q> operator, so we can compose our
calls like this:</p>
<div class="highlight"><pre><span/><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span>
<span class="w">        </span><span class="n">count</span><span class="p">()</span><span class="w"> </span><span class="o">|</span>
<span class="w">        </span><span class="n">take_n</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span><span class="w"> </span><span class="o">|</span>
<span class="w">        </span><span class="n">filter</span><span class="p">([](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">})</span><span class="w"> </span><span class="o">|</span>
<span class="w">        </span><span class="n">map</span><span class="p">([](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">result</span><span class="p">)</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">" "</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>One way we can get this working is to first create a type that wraps an
algorithm and an <code>operator|</code> implementation between a lhs <code>generator</code>
and a rhs of our type:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">filter_t</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">filter_t</span><span class="p">(</span><span class="n">Predicate</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">_pred</span><span class="p">(</span><span class="n">pred</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="k">operator</span><span class="p">()(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span><span class="w"> </span><span class="k">const</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">_pred</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>
<span class="w">                </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">Predicate</span><span class="w"> </span><span class="n">_pred</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="k">operator</span><span class="o">|</span><span class="p">(</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">lhs</span><span class="p">,</span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">filter_t</span><span class="o">&lt;</span><span class="n">Predicate</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">rhs</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">rhs</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">lhs</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>Here, <code>filter_t</code> holds the <code>Predicate</code> we want to use, and <code>operator|</code>
applies it on the given <code>generator</code>. This works, but we wouldn't be able
to instantiate <code>filter_t</code> with a lambda like in the above chaining
example without specifying the Predicate type in the call. If we want to
leverage type deduction, we can create a simple helper function that
creates a <code>filter_t</code> from a given argument:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">filter</span><span class="p">(</span><span class="n">Predicate</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">filter_t</span><span class="o">&lt;</span><span class="n">Predicate</span><span class="o">&gt;</span><span class="p">(</span><span class="n">pred</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>With this we can call <code>| filter(/* predicate */)</code> on a generator and get
back a filtered generator. Full implementation for <code>take_n</code>, <code>filter</code>
and <code>map</code> would be:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">take_n_t</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">take_n_t</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">_n</span><span class="p">(</span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="k">operator</span><span class="p">()(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span><span class="w"> </span><span class="k">const</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="o">++</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">_n</span><span class="p">)</span>
<span class="w">                </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">            </span><span class="k">else</span>
<span class="w">                </span><span class="k">return</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">_n</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="k">operator</span><span class="o">|</span><span class="p">(</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">lhs</span><span class="p">,</span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">take_n_t</span><span class="o">&amp;</span><span class="w"> </span><span class="n">rhs</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">rhs</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">lhs</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">auto</span><span class="w"> </span><span class="n">take_n</span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">take_n_t</span><span class="p">(</span><span class="n">n</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">filter_t</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">filter_t</span><span class="p">(</span><span class="n">Predicate</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">_pred</span><span class="p">(</span><span class="n">pred</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">template</span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="k">operator</span><span class="p">()(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span><span class="w"> </span><span class="k">const</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">            </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">_pred</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>
<span class="w">                </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">Predicate</span><span class="w"> </span><span class="n">_pred</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="k">operator</span><span class="o">|</span><span class="p">(</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">lhs</span><span class="p">,</span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">filter_t</span><span class="o">&lt;</span><span class="n">Predicate</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">rhs</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">rhs</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">lhs</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">filter</span><span class="p">(</span><span class="n">Predicate</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">filter_t</span><span class="o">&lt;</span><span class="n">Predicate</span><span class="o">&gt;</span><span class="p">(</span><span class="n">pred</span><span class="p">);</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">BinaryOperation</span><span class="o">&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">map_t</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">map_t</span><span class="p">(</span><span class="n">BinaryOperation</span><span class="w"> </span><span class="n">op</span><span class="p">)</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">_op</span><span class="p">(</span><span class="n">op</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>

<span class="w">    </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="k">operator</span><span class="p">()(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span><span class="w"> </span><span class="k">const</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">            </span><span class="k">co_yield</span><span class="w"> </span><span class="n">_op</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">BinaryOperation</span><span class="w"> </span><span class="n">_op</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">BinaryOperation</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="k">operator</span><span class="o">|</span><span class="p">(</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">lhs</span><span class="p">,</span>
<span class="w">    </span><span class="k">const</span><span class="w"> </span><span class="n">map_t</span><span class="o">&lt;</span><span class="n">BinaryOperation</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">rhs</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">rhs</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">lhs</span><span class="p">));</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">BinaryOperation</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">map</span><span class="p">(</span><span class="n">BinaryOperation</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">map_t</span><span class="o">&lt;</span><span class="n">BinaryOperation</span><span class="o">&gt;</span><span class="p">(</span><span class="n">op</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>With this approach, we can apply our algorithms over a generator without
having to introduce a different type. They also compose very nicely, the
only slightly odd thing being using the <code>|</code> operator (though as I
mentioned, there is a precedent for this in Boost and chances are it
might show up in other places in the future).</p>

<h2>Unified Call Syntax</h2>

<p>One thing that would've made things even easier but unfortunately was
not approved for C++17 is <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4165.pdf">unified call
syntax</a>.
At a high level, unified call syntax would make the compiler try to
resolve <code>x.f()</code> to <code>f(x)</code> if <code>decltype(x)</code> doesn't have an <code>f()</code> member
function but there is a free function <code>f(decltype(x))</code>. Similarly, if no
<code>f(decltype(x))</code> exists but <code>decltype(x)</code> has a member function <code>f()</code>,
<code>f(x)</code> would resolve to the member function call <code>x.f()</code>.</p>

<p>If it's not obvious, unified call syntax would allow us to easily create
extension methods. We would be able to revert our algorithm code to the
first version:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">take_n</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="o">++</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">n</span><span class="p">)</span>
<span class="w">            </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="w">        </span><span class="k">else</span>
<span class="w">            </span><span class="k">return</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">Predicate</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">filter</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="n">Predicate</span><span class="w"> </span><span class="n">pred</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">pred</span><span class="p">(</span><span class="n">item</span><span class="p">))</span>
<span class="w">            </span><span class="k">co_yield</span><span class="w"> </span><span class="n">item</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">BinaryOperation</span><span class="o">&gt;</span>
<span class="k">auto</span><span class="w"> </span><span class="n">map</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">experimental</span><span class="o">::</span><span class="n">generator</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">gen</span><span class="p">,</span><span class="w"> </span><span class="n">BinaryOperation</span><span class="w"> </span><span class="n">op</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">gen</span><span class="p">)</span>
<span class="w">        </span><span class="k">co_yield</span><span class="w"> </span><span class="n">op</span><span class="p">(</span><span class="n">item</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>But now this becomes very composable as calling <code>take_n</code>, <code>filter</code> or
<code>map</code> on a generator would resolve to the free functions if the
<code>generator</code> itself does not have them as members:</p>
<div class="highlight"><pre><span/><span class="kt">int</span><span class="w"> </span><span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">=</span>
<span class="w">        </span><span class="n">count</span><span class="p">().</span>
<span class="w">        </span><span class="n">take_n</span><span class="p">(</span><span class="mi">100</span><span class="p">).</span>
<span class="w">        </span><span class="n">filter</span><span class="p">([](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="p">}).</span>
<span class="w">        </span><span class="n">map</span><span class="p">([](</span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>

<span class="w">    </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">auto</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="n">result</span><span class="p">)</span>
<span class="w">        </span><span class="n">std</span><span class="o">::</span><span class="n">cout</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="n">item</span><span class="w"> </span><span class="o">&lt;&lt;</span><span class="w"> </span><span class="s">" "</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The above currently does not compile but it should (disclaimer: slight
tweaks might be required) if unified call syntax becomes part of the
standard.</p>

<h2>In Summary</h2>

<p>We went over a couple of alternatives to implement some common
algorithms over C++ generators with a focus on composability:</p>

<ul>
<li>Stand-alone functions are simple but don't compose very well.</li>
<li>Using a decorator works, but is not ideal from a design point of
view and not very idiomatic.</li>
<li>Using the pipe operator for chaining and helper types for the
algorithms is the best approach today.</li>
<li>Unified call syntax would simplify things a lot, enabling a
mechanism to implement these algorithms as extension methods.</li>
</ul>
]]></description>
      <pubDate>Sun, 09 Oct 2016 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/08/17/concepts-and-modules.html</link>
      <guid>https://vladris.com/blog/2016/08/17/concepts-and-modules.html</guid>
      <title><![CDATA[Concepts and Modules]]></title>
      <description><![CDATA[<h1>Concepts and Modules</h1>

<p>As a follow up to my previous post, I want to talk about two major new
C++ features that keep not making it into the standard, namely
<em>Concepts</em> and <em>Modules</em>. These would have a significant impact on the
code examples I provided while discussing dependency injection, so
here's a quick peek into the future:</p>

<h2>Concepts</h2>

<p>One way to think about concepts is that concepts are to templates what
interfaces are to classes. Similarly to how interfaces specify a
contract which implementing types must satisfy, concepts specify a
contract which template argument types must satisfy. The main difference
is that interfaces/classes enable runtime polymorphism while
concepts/templates enable polymorphism at compile-time.</p>

<p>Runtime polymorphism:</p>
<div class="highlight"><pre><span/><span class="c1">// Our interface</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">IEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">IEngine</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// One implementation</span>
<span class="k">class</span><span class="w"> </span><span class="nc">V6Engine</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">IEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>

<span class="c1">// Another implementation</span>
<span class="k">class</span><span class="w"> </span><span class="nc">V8Engine</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">IEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>

<span class="c1">// A function that works against the interface</span>
<span class="kt">void</span><span class="w"> </span><span class="n">StartEngine</span><span class="p">(</span><span class="n">IEngine</span><span class="o">&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">engine</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span><span class="w"> </span><span class="n">StartEngines</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">V6Engine</span><span class="w"> </span><span class="n">v6engine</span><span class="p">;</span>
<span class="w">    </span><span class="n">V8Engine</span><span class="w"> </span><span class="n">v8engine</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// calls Start() on V6Engine instance passed as IEngine</span>
<span class="w">    </span><span class="n">StartEngine</span><span class="p">(</span><span class="n">v6engine</span><span class="p">);</span>
<span class="w">    </span><span class="c1">// calls Start() on V8Engine instance passed as IEngine</span>
<span class="w">    </span><span class="n">StartEngine</span><span class="p">(</span><span class="n">v8engine</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Here, we have a single <code>StartEngine</code> function which works against an
interface. Calling <code>Start()</code> for that interface involves a virtual
function call, which means that at runtime, given an object of a type
implementing <code>IEngine</code>, the code needs to figure out which function of
the implementing type to call. For <code>V6Engine</code>, <code>IEngine::Start()</code> is
<code>V6Engine::Start();</code> for <code>V8Engine</code>, <code>IEngine::Start()</code> is
<code>V8Engine::Start()</code>. Our classes have a vtable - a table containing this
mapping, so a virtual call looks up the actual function to call in the
vtable.</p>

<p>This is the <q>classical</q> object-oriented way of dispatching calls. The
advantage of this approach is that it works across binaries<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup> (we can
export <code>StartEngine</code> from a shared library and pass in an external
<code>IEngine</code> implementation to it), the disadvantage is the extra
redirection - implementing classes must have a vtable and call
resolution involves jumping through it.</p>

<p>Compile-time polymorphism:</p>
<div class="highlight"><pre><span/><span class="c1">// One implementation</span>
<span class="k">class</span><span class="w"> </span><span class="nc">V6Engine</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>

<span class="c1">// Another implementation</span>
<span class="k">class</span><span class="w"> </span><span class="nc">V8Engine</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>

<span class="c1">// A generic function</span>
<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">TEngine</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">StartEngine</span><span class="p">(</span><span class="n">TEngine</span><span class="o">&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">engine</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
<span class="p">}</span>

<span class="kt">void</span><span class="w"> </span><span class="n">StartEngines</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">V6Engine</span><span class="w"> </span><span class="n">v6engine</span><span class="p">;</span>
<span class="w">    </span><span class="n">V8Engine</span><span class="w"> </span><span class="n">v8engine</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// calls Start() on V6Engine, this instantiates</span>
<span class="w">    </span><span class="c1">// StartEngine&lt;V6Engine&gt;(V6Engine&amp; engine)</span>
<span class="w">    </span><span class="n">StartEngine</span><span class="p">(</span><span class="n">v6engine</span><span class="p">);</span>
<span class="w">    </span><span class="c1">// calls Start() on V8Engine, this instantiates</span>
<span class="w">    </span><span class="c1">// StartEngine&lt;V8Engine&gt;(V8Engine&amp; engine)</span>
<span class="w">    </span><span class="n">StartEngine</span><span class="p">(</span><span class="n">v8engine</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>A few differences to note here: we don't have an <code>IEngine</code> interface
anymore and the two types we use, <code>V6Engine</code> and <code>V8Engine</code>, no longer
have virtual functions. Calling <code>V6Engine::Start()</code> or
<code>V8Engine::Start()</code> now no longer involves a virtual call. The two
<code>StartEngine</code> calls are actually made to different functions now - at
compile time, whenever the compiler encounters a call to <code>StartEngine</code>
with a new type, it instantiates the template, meaning it creates a new
function based on that template with the template type as the provided
type. We actually end up with one function that can start a <code>V6Engine</code>
and one that can start <code>V8Engine</code>, both produced from the same template.</p>

<p>This is compile-time polymorphism, the advantage being that everything
is determined during build - no virtual calls etc., the disadvantage
being that the compiler needs to have a definition of the template
available whenever it needs to create a new instance<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>. In this case
we can't encapsulate what happens inside <code>StartEngine</code> if we want
others to be able to call the function.</p>

<h3>With Concepts</h3>

<p>The above works just fine, the problem being that, in general, if you
have a templated function, it's not obvious what contracts do the types
it expects need to satisfy. For example, our <code>StartEngine</code> expects that
the given type has a <code>Start()</code> function it can call. This isn't obvious
from the function declaration though. Also, compiler errors when
templates cannot be instantiated are notoriously hard to decipher. The
proposed solution to both of the above are concepts. Here is how an
engine concept would look like:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">TEngine</span><span class="o">&gt;</span>
<span class="k">concept</span><span class="w"> </span><span class="nc">bool</span><span class="w"> </span><span class="n">Engine</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="k">requires</span><span class="p">(</span><span class="n">TEngine</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">{</span><span class="w"> </span><span class="n">engine</span><span class="p">.</span><span class="n">Start</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>
<span class="w">        </span><span class="p">{</span><span class="w"> </span><span class="n">engine</span><span class="p">.</span><span class="n">Stop</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>This defines the <code>Engine</code> concept to require any type satisfying it to
have a <code>Start()</code> function and a <code>Stop()</code> function. <code>StartEngine</code> would
then be able to explicitly say what kind of types it expects:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="n">Engine</span><span class="w"> </span><span class="n">TEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">StartEngine</span><span class="p">(</span><span class="n">TEngine</span><span class="o">&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">engine</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>It is now clear from the function declaration that <code>StartEngine</code> expects
a type satisfying the <code>Engine</code> concept. We can look at the concept
definition to see what we need to implement on our type. The compiler
would also be able to issue much clearer errors when the type we pass in
is missing one of the concept requirements.</p>

<p>Unfortunately, while several proposals for concepts have been put
forward in the past years, they weren't approved to be part of the
C++17 standard. That being said, it's fairly certain that they will
eventually make it into the standard.</p>

<h2>Modules</h2>

<p>Another noteworthy feature are modules: currently, the <code>#include</code>
directive textually includes the given file into the source file being
compiled. This has a lot of build-time overhead (same header files get
compiled over and over as they are included in various source files) and
forces us to be extra-careful in how we scope things: what goes in a
header file vs. what goes in a source file etc.</p>

<p>Modules aim to replace the header/source file split and provide a better
way to group components and expose functionality. For example, here is a
header/source file pair from my previous post:</p>
<div class="highlight"><pre><span/><span class="c1">// ICar.h</span>
<span class="cp">##pragma once</span>
<span class="cp">##include "IEngine.h"</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">ICar</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Drive</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">ICar</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeCar</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="n">engine</span><span class="p">);</span>
<span class="n">Car</span><span class="p">.</span><span class="n">cpp</span><span class="o">:</span>

<span class="c1">// Car.cpp</span>
<span class="cp">##include "ICar.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Car</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">ICar</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="n">Car</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="w">         </span><span class="o">:</span><span class="w"> </span><span class="n">m_engine</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">))</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">()</span><span class="w"> </span><span class="k">override</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">         </span><span class="n">m_engine</span><span class="o">-&gt;</span><span class="n">Start</span><span class="p">();</span>
<span class="w">         </span><span class="c1">// drive</span>
<span class="w">         </span><span class="n">m_engine</span><span class="o">-&gt;</span><span class="n">Stop</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeCar</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Car</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>Using modules, we would have:</p>
<div class="highlight"><pre><span/><span class="k">module</span><span class="w"> </span><span class="n">Car</span><span class="p">;</span>

<span class="k">import</span><span class="w"> </span><span class="n">Engine</span><span class="p">;</span>

<span class="k">export</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">ICar</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Drive</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">ICar</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Car</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">ICar</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="n">Car</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="w">         </span><span class="o">:</span><span class="w"> </span><span class="n">m_engine</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">))</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">()</span><span class="w"> </span><span class="k">override</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">         </span><span class="n">m_engine</span><span class="o">-&gt;</span><span class="n">Start</span><span class="p">();</span>
<span class="w">         </span><span class="c1">// drive</span>
<span class="w">         </span><span class="n">m_engine</span><span class="o">-&gt;</span><span class="n">Stop</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>

<span class="k">export</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeCar</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="n">engine</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Car</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>This is now a single file where we import the <code>Engine</code> module (instead
of <code>#include</code>), we provide the interface and concrete implementation,
the factory function, and we mark publicly-visible declarations with the
<code>export</code> keyword.</p>

<p>Like Concepts, Modules haven't made it into the C++17 standard, but
MSVC has a working implementation as of VS2015 Update 1.</p>

<h2>Dependency Injection in the Future</h2>

<p>So putting the above together, here is how dependency injection in C++
might look like in the not too far future:</p>
<div class="highlight"><pre><span/><span class="c1">// Engine.m</span>
<span class="k">module</span><span class="w"> </span><span class="n">Engine</span><span class="p">;</span>

<span class="k">export</span><span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">TEngine</span><span class="o">&gt;</span>
<span class="k">concept</span><span class="w"> </span><span class="nc">bool</span><span class="w"> </span><span class="n">Engine</span><span class="p">()</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="k">requires</span><span class="p">(</span><span class="n">TEngine</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="p">{</span><span class="w"> </span><span class="n">engine</span><span class="p">.</span><span class="n">Start</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>
<span class="w">        </span><span class="p">{</span><span class="w"> </span><span class="n">engine</span><span class="p">.</span><span class="n">Stop</span><span class="p">()</span><span class="w"> </span><span class="p">};</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="c1">// V8Engine.m</span>
<span class="k">module</span><span class="w"> </span><span class="n">V8Engine</span><span class="p">;</span>

<span class="k">export</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">V8Engine</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Start</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// start the engine }</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="c1">// stop the engine }</span>
<span class="p">};</span>

<span class="c1">// Car.m</span>
<span class="k">module</span><span class="w"> </span><span class="n">Car</span><span class="p">;</span>

<span class="k">import</span><span class="w"> </span><span class="n">Engine</span><span class="p">;</span>
<span class="k">import</span><span class="w"> </span><span class="n">V8Engine</span><span class="p">;</span>

<span class="k">export</span><span class="w"> </span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="n">Engine</span><span class="w"> </span><span class="n">TEngine</span><span class="o">&gt;</span>
<span class="k">requires</span><span class="w"> </span><span class="n">DefaultConstructible</span><span class="o">&lt;</span><span class="n">TEngine</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Car</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
<span class="w">        </span><span class="c1">// drive</span>
<span class="w">        </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Stop</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">TEngine</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// Explicit instantiation exported from this module so clients</span>
<span class="c1">// won't have to re-instantiate the template for V8Engine type</span>
<span class="k">export</span><span class="w"> </span><span class="k">class</span><span class="w"> </span><span class="nc">Car</span><span class="o">&lt;</span><span class="n">V8Engine</span><span class="o">&gt;</span><span class="p">;</span>
</pre></div>

<p>This can be used as follows:</p>
<div class="highlight"><pre><span/><span class="k">import</span><span class="w"> </span><span class="n">Car</span><span class="p">;</span>
<span class="p">...</span>
<span class="n">Car</span><span class="o">&lt;</span><span class="n">V8Engine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">car</span><span class="p">;</span>
<span class="n">car</span><span class="p">.</span><span class="n">Drive</span><span class="p">();</span>
</pre></div>

<p>This would be the equivalent of Dependency Injection with Templates I
mentioned in the previous post.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>As long as binaries are compiled with the same compiler. Otherwise
the code produced by different compilers might have different vtable
layouts and different name mangling. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>Other disadvantages are slower compile times and potential code
bloat, as each template instantiation gets translated into a new
function. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Wed, 17 Aug 2016 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/07/06/dependency-injection-in-c.html</link>
      <guid>https://vladris.com/blog/2016/07/06/dependency-injection-in-c.html</guid>
      <title><![CDATA[Dependency Injection in C++]]></title>
      <description><![CDATA[<h1>Dependency Injection in C++</h1>

<p>In this post, I will switch gears from functional C++ to object oriented
C++ and talk about dependency injection.</p>

<p>Let's start with a simple example: take a <code>Car</code> class with a <code>Drive()</code>
method. Let's say this class contains a <code>V8Engine</code> attribute with
<code>Start()</code> and <code>Stop()</code> methods. An initial implementation might look
like this:</p>

<p><em>V8Engine.h (publicly visible)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>

<span class="k">class</span><span class="w"> </span><span class="nc">V8Engine</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Start</span><span class="p">();</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">();</span>
<span class="p">};</span>
</pre></div>

<p><em>V8Engine.cpp</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##include "V8Engine.h"</span>

<span class="n">V8Engine</span><span class="o">::</span><span class="n">Start</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// start the engine</span>
<span class="p">}</span>

<span class="n">V8Engine</span><span class="o">::</span><span class="n">Stop</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// stop the engine</span>
<span class="p">}</span>
</pre></div>

<p><em>Car.h (publicly visible)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>
<span class="cp">##include "V8Engine.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Car</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">();</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">V8Engine</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p><em>Car.cpp</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##include "Car.h"</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">Car::Drive</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
<span class="w">    </span><span class="c1">// drive</span>
<span class="w">    </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Stop</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<h2>Dependency Injection with Interfaces</h2>

<p>In the above example, <code>Car</code> is tightly coupled to <code>V8Engine</code>, meaning we
can't create a car without a concrete engine implementation. If we want
the ability to swap various engines or use a mock engine during testing,
we could reverse the dependency by creating an <code>IEngine</code> interface and
decoupling <code>Car</code> from the concrete <code>V8Engine</code> implementation. This way,
we only expose an <code>IEngine</code> interface and a factory function. <code>Car</code> can
work against that:</p>

<p><em>IEngine.h (publicly visible)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">IEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">IEngine</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeV8Engine</span><span class="p">();</span>
</pre></div>

<p><em>V8Engine.cpp</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##include "IEngine.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">V8Engine</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">IEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* start the engine */</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* stop the engine */</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeV8Engine</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">V8Engine</span><span class="o">&gt;</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p><em>Car.h (publicly visible)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>
<span class="cp">##include "IEngine.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Car</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="n">Car</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="w">        </span><span class="o">:</span><span class="w"> </span><span class="n">m_engine</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">))</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">();</span>
<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p><em>Car.cpp</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##include "Car.h"</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">Car::Drive</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">m_engine</span><span class="o">-&gt;</span><span class="n">Start</span><span class="p">();</span>
<span class="w">    </span><span class="c1">// drive</span>
<span class="w">    </span><span class="n">m_engine</span><span class="o">-&gt;</span><span class="n">End</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<h2>Notes</h2>

<h3>A note on headers</h3>

<p>Headers simply get textually included in each compilation unit by the
<code>#include</code> directive. It is not mandatory to provide a header file for
each class declaration. If a class can be scoped to a single source
file, then it doesn't need a header declaration (for example the
<code>V8Engine</code> class above does not need a V8Engine.h header corresponding
to the V8Engine.cpp). It is also a good idea to have public headers and
internal headers: public headers contain the public API surface and can
be included by other parts of the system, while internal headers are
only used within the component and should not be included by external
code.</p>

<p>Default should be the least visible: try to keep everything inside the
cpp file (like V8Engine.cpp). If that is not enough, an internal header
might do. A declartion should be pulled into a public header only when
external components need to reference it.</p>

<h3>A note on interfaces</h3>

<p>It's a good idea to declare a default virtual destructor: if a deriving
type has a destructor, it won't get called if we store an upcast
pointer to the interface unless the interface declares a virtual
destructor. Note a destructor does not to be expicitly defined -
compiler might generate a default one.</p>

<p>MSVC compiler provides a <code>__declspec(novtable)</code><sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup> custom attribute
which tells the compiler not to generate a vtable for pure abstract
classes. This reduces code size. Below is the <code>IEngine</code> declaration with
this attribute:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">__declspec</span><span class="p">(</span><span class="n">novtable</span><span class="p">)</span><span class="w"> </span><span class="n">IEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">IEngine</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>I won't include it in the code samples in this post, but it's worth
keeping in mind when working with MSVC.</p>

<h3>A note on factory functions</h3>

<p>When working with interfaces as opposed to concrete types, we use
factory functions to get object instances. Below is a possible naming
convention, taking object ownership into account:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IFoo</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeFoo</span><span class="p">();</span>
<span class="n">IFoo</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">UseFoo</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">IFoo</span><span class="o">&gt;</span><span class="w"> </span><span class="n">GetFoo</span><span class="p">();</span>
</pre></div>

<p>The first function, <code>MakeFoo</code>, returns a unique pointer, passing
ownership to the caller. Like in the example above, the <code>unqiue_ptr</code> can
be moved into the object, which ends up owning it. Use a Make when each
call creates a new instance.</p>

<p>The second function implies there already exists an <code>IFoo</code> object which
is owned by someone else, with the guarantee that it will outlive the
caller. In that case, there is no need for pointers and we can simply
return a reference to the object. This can be used, for example, for
singletons. Below is an example of a singleton <code>Engine</code>:</p>
<div class="highlight"><pre><span/><span class="n">IEngine</span><span class="o">&amp;</span><span class="w"> </span><span class="nf">UseEngine</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="k">auto</span><span class="w"> </span><span class="n">instance</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Engine</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="o">*</span><span class="n">instance</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The third function, <code>GetFoo</code>, implies shared ownership - we get an
object that other objects might hold a reference to, but we don't have
the lifetime guarantee a singleton would give us, so we need to use a
shared pointer to make sure the object is kept alive long enough.</p>

<h2>Mocking</h2>

<p>Since <code>Car</code> now works with an <code>IEngine</code> interface, in test code we can
mock the engine:</p>

<p><em>Test.cpp</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##include "Car.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">MockEngine</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">IEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* mock logic */</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* mock logic */</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">Test</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Car</span><span class="w"> </span><span class="n">car</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">MockEngine</span><span class="o">&gt;</span><span class="p">());</span>

<span class="w">    </span><span class="c1">// Test Car without a real Engine</span>
<span class="p">}</span>
</pre></div>

<p>We can also expose <code>Car</code> as a simple interface, hiding its
implementation details, in which case we would end up with the
following:</p>

<p><em>ICar.h (publicly visible)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>
<span class="cp">##include "IEngine.h"</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">ICar</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Drive</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">ICar</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeCar</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="n">engine</span><span class="p">);</span>
</pre></div>

<p><em>Car.cpp</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##include "ICar.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Car</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">ICar</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="n">Car</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="w">         </span><span class="o">:</span><span class="w"> </span><span class="n">m_engine</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">))</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">()</span><span class="w"> </span><span class="k">override</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">         </span><span class="n">m_engine</span><span class="o">-&gt;</span><span class="n">Start</span><span class="p">();</span>
<span class="w">         </span><span class="c1">// drive</span>
<span class="w">         </span><span class="n">m_engine</span><span class="o">-&gt;</span><span class="n">Stop</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeCar</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Car</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>Test would become:</p>
<div class="highlight"><pre><span/><span class="cp">##include "ICar.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">MockEngine</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">IEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* mock logic */</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* mock logic */</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">Test</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">car</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MakeCar</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">MockEngine</span><span class="o">&gt;</span><span class="p">());</span>

<span class="w">    </span><span class="c1">// Test ICar without a real Engine</span>
<span class="p">}</span>
</pre></div>

<p>Note this allows the caller to pass in any <code>IEngine</code>. We provide an
out-of-the-box <code>V8Engine</code> but other engines can be injected when <code>Car</code>
gets constructed. The headers IEngine.h and ICar.h are public per our
above defintion.</p>

<p>In general, it's great if we can get the rest of the component code and
unit tests to work against the interface. Sometimes though we might need
to know more about the actual implementation inside our component, even
if externally we only expose an interface. In that case, we can add an
internal Car.h header:</p>

<p><em>Car.h (internal)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>
<span class="cp">##include "ICar.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">Car</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">ICar</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="n">Car</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="w">         </span><span class="o">:</span><span class="w"> </span><span class="n">m_engine</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">))</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">()</span><span class="w"> </span><span class="k">override</span><span class="p">;</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p><em>Car.cpp</em> becomes:</p>
<div class="highlight"><pre><span/><span class="cp">##include "Car.h"</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">Car::Drive</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
<span class="w">    </span><span class="c1">// drive</span>
<span class="w">    </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Stop</span><span class="p">();</span>
<span class="p">}</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeCar</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">IEngine</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">engine</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Car</span><span class="o">&gt;</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">engine</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>Now we can include the internal header, and, while not necessarily
recommended, we can cast <code>ICar</code> to <code>Car</code> inside the component:</p>
<div class="highlight"><pre><span/><span class="k">auto</span><span class="w"> </span><span class="n">icar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MakeCar</span><span class="p">(</span><span class="n">MakeV8Engine</span><span class="p">());</span>
<span class="k">auto</span><span class="o">&amp;</span><span class="w"> </span><span class="n">car</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">static_cast</span><span class="o">&lt;</span><span class="n">Car</span><span class="o">&amp;&gt;</span><span class="p">(</span><span class="o">*</span><span class="n">car</span><span class="p">);</span>
</pre></div>

<p>Another trick if needing access to internals (again, not something
necessarily recommended), is to make the unit test class testing <code>Car</code> a
friend of the <code>Car</code> class, in which case it can access its private
members.</p>

<p>In summary, with this approach we are able to:</p>

<ul>
<li>Hide implementation details in the .cpp files</li>
<li>Work against abstract interfaces</li>
<li>Inject dependencies during object construction</li>
</ul>

<h2>Dependecy Injection with Templates</h2>

<p>An alternative to the above is to use templates. In this case, we would
have to provide the implementation inside the header file, as code needs
to be available when templates get instantiated:</p>

<p><em>V8Engine.h (publicly visible)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>

<span class="k">class</span><span class="w"> </span><span class="nc">V8Engine</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Start</span><span class="p">();</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">();</span>
<span class="p">};</span>
</pre></div>

<p><em>V8Engine.cpp</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##include "V8Engine.h"</span>

<span class="n">V8Engine</span><span class="o">::</span><span class="n">Start</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// start the engine</span>
<span class="p">}</span>

<span class="n">V8Engine</span><span class="o">::</span><span class="n">Stop</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// stop the engine</span>
<span class="p">}</span>
</pre></div>

<p><em>Car.h (publicly visible)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">TEngine</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Car</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
<span class="w">        </span><span class="c1">// drive</span>
<span class="w">        </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Stop</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">TEngine</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p>Note <code>Car</code> is implemented in the header and <code>V8Engine</code> is also a
publicly visible header. Now we can create an instance of <code>Car</code> like
this:</p>
<div class="highlight"><pre><span/><span class="cp">##include "V8Engine.h"</span>
<span class="cp">##include "Car.h"</span>

<span class="p">...</span>

<span class="n">Car</span><span class="o">&lt;</span><span class="n">V8Engine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">car</span><span class="p">;</span>
</pre></div>

<p>Mocking the engine in test code would look like this:</p>
<div class="highlight"><pre><span/><span class="cp">##include "Car.h"</span>

<span class="k">class</span><span class="w"> </span><span class="nc">MockEngine</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Start</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* mock logic */</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="nf">Stop</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="cm">/* mock logic */</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">Test</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Car</span><span class="o">&lt;</span><span class="n">MockEngine</span><span class="o">&gt;</span><span class="w"> </span><span class="n">car</span><span class="p">;</span>

<span class="w">    </span><span class="c1">// Test Car without a real Engine</span>
<span class="p">}</span>
</pre></div>

<p>With this approach we are able to:</p>

<ul>
<li>Inject dependencies during template instantiation</li>
<li>No need for virtual calls (note <code>TEngine</code> is not an interface, so
calls can be resolved at compile-time)</li>
<li><code>Car&lt;T&gt;</code> can be default-constructed</li>
</ul>

<p>A drawback here is we expose the implementation details of <code>Car</code> inside
the header file and we have to make this publicly visible.</p>

<h2>Hybrid Approach</h2>

<p>We can use a hybrid approach if we don't need an externally injected
<code>Engine</code>. Say our component provides a <code>V8Engine</code>, a <code>V6Engine</code>, and we
have a <code>MockEngine</code> used during testing. We have the same
componentization requirements but don't need to expose all the details
to consumers. In that case we could have something like this:</p>

<p><em>ICar.h (publicly visible)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>

<span class="k">struct</span><span class="w"> </span><span class="nc">ICar</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="kt">void</span><span class="w"> </span><span class="nf">Drive</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="k">virtual</span><span class="w"> </span><span class="o">~</span><span class="n">ICar</span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">default</span><span class="p">;</span>
<span class="p">};</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeV8Car</span><span class="p">();</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeV6Car</span><span class="p">();</span>
</pre></div>

<p><em>Car.h (internal)</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##pragma once</span>
<span class="cp">##include "ICar.h"</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">TEngine</span><span class="o">&gt;</span>
<span class="k">class</span><span class="w"> </span><span class="nc">Car</span><span class="w"> </span><span class="o">:</span><span class="w"> </span><span class="k">public</span><span class="w"> </span><span class="n">ICar</span>
<span class="p">{</span>
<span class="k">public</span><span class="o">:</span>
<span class="w">    </span><span class="kt">void</span><span class="w"> </span><span class="n">Drive</span><span class="p">()</span><span class="w"> </span><span class="k">override</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Start</span><span class="p">();</span>
<span class="w">        </span><span class="c1">// drive</span>
<span class="w">        </span><span class="n">m_engine</span><span class="p">.</span><span class="n">Stop</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>

<span class="k">private</span><span class="o">:</span>
<span class="w">    </span><span class="n">TEngine</span><span class="w"> </span><span class="n">m_engine</span><span class="p">;</span>
<span class="p">};</span>
</pre></div>

<p><em>Car.cpp</em>:</p>
<div class="highlight"><pre><span/><span class="cp">##include "Car.h"</span>
<span class="cp">##include "V8Engine.h"</span>
<span class="cp">##include "V6Engine.h"</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeV8Car</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Car</span><span class="o">&lt;</span><span class="n">V8Engine</span><span class="o">&gt;&gt;</span><span class="p">();</span>
<span class="p">}</span>

<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">ICar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">MakeV6Car</span><span class="p">();</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Car</span><span class="o">&lt;</span><span class="n">V6Engine</span><span class="o">&gt;&gt;</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>Test would remain the same as in the example above, where we worked
against a <code>Car</code> type (not an <code>ICar</code>) which we instantiate with a
<code>MockEngine</code>.</p>

<p>With this approach:</p>

<ul>
<li>Our external API is an interface</li>
<li>Internally we still inject the dependency using a template</li>
</ul>

<p>With this approach, we do have an interface and virtual calls for <code>Car</code>
but not for <code>TEngine</code> types. One drawback with this approach is that
consumers cannot inject their own Engine type: we can only create cars
with engines that are known within our component.</p>

<h2>Summary</h2>

<p>We decoupled <code>Car</code> from <code>V8Engine</code> and looked at three ways of injecting
the dependency:</p>

<ul>
<li>Using interfaces, where dependency is injected at runtime during
object creation</li>
<li>Using templates, where dependency is injected at compile-time during
template instantiation</li>
<li>A hybrid approach which uses templates internally but exposes only
interfaces publicly</li>
</ul>

<p>Each of these approaches has pros and cons, the tradeoffs mostly being
around encapsulation (how much of the component code we expose
publicly), runtime (templates are instantiated at compile-time so no
virtual calls etc.), type constraints (with templates we don't require
engines to implement a particular <code>IEngine</code> interface), and flexibility
(with the hybrid approach we can't inject an external engine, we can
only use what the component has available internally).</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>For more details on <code>novtable</code>, see
<a href="https://msdn.microsoft.com/en-us/library/k13k85ky.aspx">MSDN</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Wed, 06 Jul 2016 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/04/24/abusing-maps.html</link>
      <guid>https://vladris.com/blog/2016/04/24/abusing-maps.html</guid>
      <title><![CDATA[(Ab)using Maps]]></title>
      <description><![CDATA[<h1>(Ab)using Maps</h1>

<h2>Mapping pattern</h2>

<p>Using hash maps (or dictionaries, or lookups) is a very natural way of
coding in some languages, especially dynamic languages, where usually an
object can be treated as a map itself, to which attributes and methods
can be added or removed at runtime.</p>

<p>In practice though, maps are often used to convert a value of one type
into a value of a different type. It is not uncommon to have very small
maps like</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="n">Foo</span><span class="p">,</span><span class="w"> </span><span class="n">Bar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">fooBarMap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo1</span><span class="p">,</span><span class="w"> </span><span class="n">bar1</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo2</span><span class="p">,</span><span class="w"> </span><span class="n">bar2</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo3</span><span class="p">,</span><span class="w"> </span><span class="n">bar3</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="p">...</span>

<span class="k">auto</span><span class="w"> </span><span class="n">bar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fooBarMap</span><span class="p">[</span><span class="n">foo</span><span class="p">];</span>
</pre></div>

<p>Here it is useful to make a distinction between the pattern and the data
structure. The coding pattern itself is great - mapping a value from a
type to a value of another type should definitely be declarative. Below
is a counterexample of non-declarative mapping:</p>
<div class="highlight"><pre><span/><span class="n">Bar</span><span class="w"> </span><span class="nf">barFromFoo</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Foo</span><span class="o">&amp;</span><span class="w"> </span><span class="n">foo</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">foo</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">foo1</span><span class="p">)</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">bar1</span><span class="p">;</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">foo</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">foo2</span><span class="p">)</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">bar2</span><span class="p">;</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">foo</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">foo3</span><span class="p">)</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">bar3</span><span class="p">;</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">}</span>
</pre></div>

<p>This is really ugly. As I mentioned in
<a href="https://vladris.com/blog/2016/01/04/clean-code-part-1.html">Clean Code - Part 1</a>,
branching should be avoided whenever possible, and this is
a good opportunity to use a declarative approach as opposed to a bunch
of branching logic. That being said, while the mapping pattern is great,
in C++ the data structure most developers default to is not the optimal
one for this.</p>

<h2>The problem with unordered_map</h2>

<p>If you are coding in C++, odds are you care a little bit about the
runtime footprint of your code. In that case, you might be surprised to
learn that, while an <code>unordered_map</code> in C++ (or a lookup or hash map or
dictionary in any other language) has an average lookup cost of <code>O(1)</code>,
there are better ways to implement the above pattern.</p>

<p>A map in C++ is implemented as a red-black tree containing buckets of
hashed values. Calling <code>at()</code> on a map implies the given key has to be
hashed and the tree traversed to find the value. Calling <code>[]</code> on an
inexistent key will add it to the data structure, which might trigger a
rebalancing of the tree. There is a lot of work happening under the
hood, and while this makes sense for an <code>unordered_map</code> of arbitrarily
large size, for small lookups it is a lot of overhead.</p>

<h2>Alternatives</h2>

<p>An alternative to <code>unordered_map</code> provided by the boost library is
<code>flat_map</code><sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. This has similar semantics to an <code>unordered_map</code>, but
the key-values are stored in a contiguous data structure so traversing
it is more efficient than walking a tree.</p>

<p>In general, there are a couple of approaches for keeping a hash map in a
linear data structure:</p>

<ul>
<li>The keys can be kept sorted, which has <code>O(N)</code> worst case insertion
since it might require all elements to be moved to fit a new one and
<code>O(logN)</code> lookup (binary search)</li>
<li>The keys can be kept unsorted, which has <code>O(1)</code> insertion (simple
append) but <code>O(N)</code> lookup (linear search)</li>
</ul>

<p>For very small-sized lookups, the cost of hashing itself might
out-weight a linear traversal, so for a small N</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="n">Foo</span><span class="p">,</span><span class="w"> </span><span class="n">Bar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">fooBarMap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo1</span><span class="p">,</span><span class="w"> </span><span class="n">bar1</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo2</span><span class="p">,</span><span class="w"> </span><span class="n">bar2</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo3</span><span class="p">,</span><span class="w"> </span><span class="n">bar3</span><span class="w"> </span><span class="p">}</span>
<span class="p">};</span>

<span class="p">...</span>

<span class="k">auto</span><span class="w"> </span><span class="n">bar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fooBarMap</span><span class="p">[</span><span class="n">foo</span><span class="p">];</span>
</pre></div>

<p>performs worse than</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="n">Foo</span><span class="p">,</span><span class="w"> </span><span class="n">Bar</span><span class="o">&gt;&gt;</span><span class="w"> </span><span class="n">fooBarMap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo1</span><span class="p">,</span><span class="w"> </span><span class="n">bar1</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo2</span><span class="p">,</span><span class="w"> </span><span class="n">bar2</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo3</span><span class="p">,</span><span class="w"> </span><span class="n">bar3</span><span class="w"> </span><span class="p">}</span>
<span class="p">}};</span>

<span class="p">...</span>

<span class="k">auto</span><span class="w"> </span><span class="n">bar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">find_if</span><span class="p">(</span>
<span class="w">    </span><span class="n">fooBarMap</span><span class="p">.</span><span class="n">cbegin</span><span class="p">(),</span>
<span class="w">    </span><span class="n">fooBarMap</span><span class="p">.</span><span class="n">cend</span><span class="p">(),</span>
<span class="w">    </span><span class="p">[](</span><span class="k">const</span><span class="w"> </span><span class="k">auto</span><span class="o">&amp;</span><span class="w"> </span><span class="n">elem</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">elem</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">foo</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>
</pre></div>

<p>On my machine (using MSVC 2015 STL implementation), for an N of 5,
<code>find_if</code> on a vector is about twice as fast as the equivalent
<code>unordered_map</code> lookup.</p>

<h2>Initialization cost</h2>

<p>There's event more hidden cost: <code>std::vector</code> manages a dynamic array
which is allocated on the heap. Having an <code>std::vector</code> initialized with
key-values as described above, even if more efficent than an
<code>unordered_map</code>, still has some associated cost in terms of heap
allocations (albeit smaller than <code>unordered_map</code>). <code>std::array</code> is a
much better suited container for cases when the key-values are known at
compile time, as <code>std::array</code> simply wraps a regular array which is not
allocated on the heap. So a more efficient (in terms of initialization
cost) way of declaring such a look up is</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">arrray</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="n">Foo</span><span class="p">,</span><span class="w"> </span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo1</span><span class="p">,</span><span class="w"> </span><span class="n">bar1</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo2</span><span class="p">,</span><span class="w"> </span><span class="n">bar2</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo3</span><span class="p">,</span><span class="w"> </span><span class="n">bar3</span><span class="w"> </span><span class="p">}</span>
<span class="p">}};</span>
</pre></div>

<p>We can still apply the <code>std::find_if</code> algorithm on this array, but we
skip a heap allocation. Depending on the template types used, we might
be able to skip any allocations whatsoever (if both types are
trivial<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup>). For example, note that <code>std::string</code>, similarly to a
vector, wraps a heap-allocated <code>char*</code> and constructing it requires heap
allocations. <code>const char*</code> to a string literal on the other hand is just
a pointer to the <code>.rodata</code> segment. So this</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span><span class="w"> </span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="s">"foo1"</span><span class="p">,</span><span class="w"> </span><span class="n">bar1</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="s">"foo2"</span><span class="p">,</span><span class="w"> </span><span class="n">bar2</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="s">"foo3"</span><span class="p">,</span><span class="w"> </span><span class="n">bar3</span><span class="w"> </span><span class="p">}</span>
<span class="p">}};</span>
</pre></div>

<p>performs three heap allocations (for <code>"foo1"</code>, <code>"foo2"</code>, and <code>"foo3"</code>),
while the (mostly) equivalent</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">array</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="p">,</span><span class="w"> </span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="s">"foo1"</span><span class="p">,</span><span class="w"> </span><span class="n">bar1</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="s">"foo2"</span><span class="p">,</span><span class="w"> </span><span class="n">bar2</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="s">"foo3"</span><span class="p">,</span><span class="w"> </span><span class="n">bar3</span><span class="w"> </span><span class="p">}</span>
<span class="p">}};</span>
</pre></div>

<p>shouldn't perform any allocations.</p>

<h2>associative_array</h2>

<p>Since in practice maps are often used to implement the above described
pattern of mapping a value from one type to a value of a different type
for a small set of known values, it would be great to combine the
efficiency of an array with the nice lookup semantics of an
<code>unordered_map</code> conatiner.</p>

<p>I propose a generic container of the following shape:</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span>
<span class="w">    </span><span class="k">typename</span><span class="w"> </span><span class="nc">TKey</span><span class="p">,</span>
<span class="w">    </span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="p">,</span>
<span class="w">    </span><span class="kt">size_t</span><span class="w"> </span><span class="n">N</span><span class="p">,</span>
<span class="w">    </span><span class="k">typename</span><span class="w"> </span><span class="nc">KeyEqual</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">key_equal</span><span class="o">&lt;</span><span class="n">TKey</span><span class="o">&gt;&gt;</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">associative_array</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">std</span><span class="o">::</span><span class="n">pair</span><span class="o">&lt;</span><span class="n">TKey</span><span class="p">,</span><span class="w"> </span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="n">m_array</span><span class="p">[</span><span class="n">N</span><span class="p">];</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">};</span>
</pre></div>

<p><code>keq_equal</code> should simply resolve to <code>==</code> for most types, but be
specialized for strings types (to use <code>strcmp</code>, <code>wcscmp</code> etc.) and allow
clients to specialize their own <code>key_equal</code> when needed.</p>
<div class="highlight"><pre><span/><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">T</span><span class="o">&gt;</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">key_equal</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">bool</span><span class="w"> </span><span class="nf">operator</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">lhs</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">rhs</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">lhs</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">rhs</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>

<span class="k">template</span><span class="w"> </span><span class="o">&lt;&gt;</span><span class="w"> </span><span class="k">struct</span><span class="w"> </span><span class="nc">key_equal</span><span class="o">&lt;</span><span class="kt">char</span><span class="o">*&gt;</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">bool</span><span class="w"> </span><span class="nf">operator</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">lhs</span><span class="p">,</span><span class="w"> </span><span class="k">const</span><span class="w"> </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">rhs</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">strcmp</span><span class="p">(</span><span class="n">lhs</span><span class="p">,</span><span class="w"> </span><span class="n">rhs</span><span class="p">)</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
<span class="p">...</span>
<span class="c1">// specializations for wchar_t and const variations of the above</span>
</pre></div>

<p>Satisfying the container concept is fairly easy (eg. <code>size()</code> would
return <code>N</code>, iterators over the member array are trivial to implement
etc.), the only interesting methods are <code>find()</code>, <code>at()</code>, and
<code>operator[]</code>:</p>
<div class="highlight"><pre><span/><span class="p">...</span>
<span class="k">struct</span><span class="w"> </span><span class="nc">associative_array</span>
<span class="p">{</span>
<span class="w">    </span><span class="p">...</span>
<span class="w">    </span><span class="n">iterator</span><span class="w"> </span><span class="n">find</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">TKey</span><span class="o">&amp;</span><span class="w"> </span><span class="n">key</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">find_if</span><span class="p">(</span>
<span class="w">            </span><span class="n">begin</span><span class="p">(),</span>
<span class="w">            </span><span class="n">end</span><span class="p">(),</span>
<span class="w">            </span><span class="p">[</span><span class="o">&amp;</span><span class="p">](</span><span class="k">const</span><span class="w"> </span><span class="k">auto</span><span class="o">&amp;</span><span class="w"> </span><span class="n">elem</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">KeyEqual</span><span class="p">{}(</span><span class="n">key</span><span class="p">,</span><span class="w"> </span><span class="n">elem</span><span class="p">.</span><span class="n">first</span><span class="p">);</span><span class="w"> </span><span class="p">});</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="n">at</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">TKey</span><span class="o">&amp;</span><span class="w"> </span><span class="n">key</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">auto</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">find</span><span class="p">(</span><span class="n">key</span><span class="p">);</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">it</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">end</span><span class="p">())</span>
<span class="w">            </span><span class="k">throw</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">out_of_range</span><span class="p">(</span><span class="s">"..."</span><span class="p">);</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">it</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="n">T</span><span class="o">&amp;</span><span class="w"> </span><span class="k">operator</span><span class="p">[](</span><span class="k">const</span><span class="w"> </span><span class="n">TKey</span><span class="o">&amp;</span><span class="w"> </span><span class="n">key</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">find</span><span class="p">(</span><span class="n">key</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">second</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">};</span>
</pre></div>

<p><code>find()</code> wraps <code>std::find_if</code> leveraging <code>KeyEqual</code> (with default
implementation as <code>key_equal</code>), <code>at()</code> wraps a bounds-checked <code>find</code>,
while <code>operator[]</code> does not check bounds. <code>const</code> implementations of the
above are also needed (identical except returning <code>const T&amp;</code>).</p>

<p>Such a container would have similar semantics to <code>std::unordered_map</code>
(minus the ability to add elements given a key not already present in
the container) and the same performance profile of <code>std::array</code>:</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">associative_array</span><span class="o">&lt;</span><span class="n">Foo</span><span class="p">,</span><span class="w"> </span><span class="n">Bar</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="o">&gt;</span><span class="w"> </span><span class="n">fooBarMap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{{</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo1</span><span class="p">,</span><span class="w"> </span><span class="n">bar1</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo2</span><span class="p">,</span><span class="w"> </span><span class="n">bar2</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">foo3</span><span class="p">,</span><span class="w"> </span><span class="n">bar3</span><span class="w"> </span><span class="p">}</span>
<span class="p">}};</span>

<span class="p">...</span>

<span class="k">auto</span><span class="w"> </span><span class="n">bar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fooBarMap</span><span class="p">[</span><span class="n">foo</span><span class="p">];</span>
</pre></div>

<p>Note the only syntax difference between above and <code>unordered_map</code> is the
container type, the extra size <code>N</code> which needs to be specified at
declaration time, and an extra pair of curly braces. In practice, this
should have a significantly better lookup time than an unordered_map for
a small N (linear time, but since N is small and no hashing or heap
traversal occurs, should clock better than a map lookup) and virtually
zero initialization time - depending on the <code>TKey</code> and <code>T</code> types used,
it is possible to declare an <code>associative_array</code> as a <code>constexpr</code> fully
evaluated at compile-time.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>Boost <code>flat_map</code> documentation is
<a href="http://www.boost.org/doc/libs/1_56_0/doc/html/boost/container/flat_map.html">here</a>. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>For more details on trivial types, see the <a href="http://www.cplusplus.com/reference/type_traits/is_trivial/">is_trivial type
trait</a>. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Sun, 24 Apr 2016 00:00:00 -0700</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/03/11/arguments-and-smart-pointers.html</link>
      <guid>https://vladris.com/blog/2016/03/11/arguments-and-smart-pointers.html</guid>
      <title><![CDATA[Arguments and Smart Pointers]]></title>
      <description><![CDATA[<h1>Arguments and Smart Pointers</h1>

<p>For efficiency reasons, C++ had a myriad of ways to pass data around. A
function can take arguments in several forms:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">T</span><span class="p">);</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">T</span><span class="o">*</span><span class="p">);</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;</span><span class="p">);</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">T</span><span class="o">**</span><span class="p">);</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">(</span><span class="n">T</span><span class="o">&amp;&amp;</span><span class="p">);</span>
</pre></div>

<p>No to mention adding <code>const</code> and smart pointers into the mix.</p>

<p>And speaking of pointers, we have raw pointers, <code>unique_ptr</code>,
<code>shared_ptr,</code> <code>CComPtr</code>/<code>ComPtr</code> (for Windows COM objects), and, if you
are working in older codebases, <code>auto_ptr</code>, and maybe even some
homebrewed refcounted pointers.</p>

<p>All of this might seem a bit daunting and make C++ seem more complicated
than it really is. One way to think about it is from the ownership
perspective: objects are resources and the key question is <q>who owns
this resource?</q>. This should dictate both how a particular resource is
allocated (and released) and the shape function arguments should take.
Lifetime is also an important consideration - a resource shouldn't be
released while other components expect it to be available, but it should
be released as soon as it is no longer needed.</p>

<p>In this post I will try to cover the various ways in which resources can
be allocated, owned, and passed around.</p>

<h2>Stack Objects and Passing Arguments</h2>

<p>The simplest, clearest thing to do is allocate objects on the stack. A
stack object doesn't involve any pointers:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>

<p>The variable <code>bar</code> of type <code>Bar</code> is created on the stack. Once the stack
frame is popped (once the function is done executing, either through a
normal return or due to an exception) the object goes away. This is the
easiest, safest thing to do. The only reasons we wouldn't always do
this are time and space requirements: lifetime-wise, we might want to
somehow use <code>bar</code> after <code>foo()</code> returns - for example we might want to
pass it around to some other object that wants to use at a later time;
in terms of space, stack memory is more limited than the heap, so large
objects are better kept on the heap to avoid overflow.</p>

<h3>Pass by value</h3>

<p>One way to get around the lifetime requirement is to pass the object by
value:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">do_suff</span><span class="p">(</span><span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">);</span><span class="w"> </span><span class="c1">// hands bar off to some other object</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>
<span class="w">    </span><span class="n">do_suff</span><span class="p">(</span><span class="n">bar</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Let's assume for this example that <code>do_suff</code> takes the argument and
sticks it into some global object which will use it as some future time.</p>

<p>The above code will simply create a copy of the object, so whatever
<code>do_suff</code> gets won't be the original resource which gets freed once the
function returns, rather a copy of it. Copying an object costs both run
time and space, but if neither are a big concern, this is a great, safe
way of ensuring resources don't get released before we're done with
them.</p>

<h3>Move</h3>

<p>C++11 introduces a cheaper way of achieving this, through move
semantics:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">do_suff</span><span class="p">(</span><span class="n">Bar</span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="n">bar</span><span class="p">);</span><span class="w"> </span><span class="c1">// hands bar off to some other object</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>
<span class="w">    </span><span class="n">do_suff</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">bar</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>With move semantics, the resource is actually <em>moved</em> into the <code>do_suff</code>
function. Once this happens, the original object is left in an undefined
state and shouldn't be used anymore. This approach is usually employed
when we have a sink argument - we <em>sink</em> <code>bar</code> to its final resting
place somewhere and <code>foo()</code> no longer cares about it after passing it
down to <code>do_stuff</code>.</p>

<p>One thing to keep in mind is that <code>move</code> is not magic, so <code>Bar</code> needs to
declare a <a href="http://en.cppreference.com/w/cpp/language/move_constructor">move
constructor</a>
in order for this to do what we expect it to do. If Bar doesn't declare
a move constructor, the above becomes a simple copy<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>.</p>

<h3>Pass by reference</h3>

<p>On the flipside, when we care about the size, so that we don't want to
create a copy of the object, but we aren't worried about the lifetime -
meaning the object we pass to <code>do_stuff</code> won't have to outlive the
function call, we can pass by reference:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">do_suff</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Bar</span><span class="o">&amp;</span><span class="w"> </span><span class="n">bar</span><span class="p">);</span><span class="w"> </span><span class="c1">// bar is only used within do_suff</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>
<span class="w">    </span><span class="n">do_suff</span><span class="p">(</span><span class="n">bar</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Note the <code>const</code> above - this means <code>do_suff</code> will use <code>bar</code> but won't
modify it. By default, arguments should be marked as <code>const</code> unless the
function does indeed need to alter the object. Regardless of constness,
in this case we pass a reference to <code>bar</code> as an argument, which is very
cheap (a reference has the same size as a pointer). The only caveat is
that <code>do_stuff</code> should not pass this to some other object that outlives
the function call (eg. a global object which tries to use it later),
because as soon as <code>foo</code> returns, the reference becomes invalid.</p>

<h3>Pass by pointer</h3>

<p>A pointer argument would look like this:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Bar</span><span class="o">*</span><span class="w"> </span><span class="n">bar</span><span class="p">);</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">Bar</span><span class="w"> </span><span class="n">bar</span><span class="p">;</span>
<span class="w">    </span><span class="n">do_stuff</span><span class="p">(</span><span class="o">&amp;</span><span class="n">bar</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>A good rule of thumb is to not do this. The difference between passing
by reference and by pointer in this case is that a pointer can be null,
while a reference can't. So passing by pointer here automatically
brings the need to perform null checks to ensure bad things don't
happen. You would need to make a very good argument to convince me
during code review that using a pointer instead of a reference is
appropriate. Unless working against a legacy API which can't be
changed, I highly discourage use of raw pointers.</p>

<h3>Summary</h3>

<p>In summary, when designing an API:</p>

<ol>
<li>Take argument by value if copying it is not a concern</li>
<li>Take argument by <code>const&amp;</code> if it's not a sink argument, meaning we
don't need to refer to it passed the function call</li>
<li>Take argument by reference (<code>&amp;</code>) if 2) but the API needs to modify
it</li>
<li>Take argument by <code>&amp;&amp;</code> if it's a sink argument, the type has a move
constructor, and copying it is expensive</li>
<li>Don't pass raw pointers around</li>
</ol>

<h2>Heap Objects and Smart Pointers</h2>

<p>In all of the examples above, <code>bar</code> was an object created on the stack.
This works great in some cases, but some objects are simply too big to
fit on the stack, or it doesn't make sense for them to do so (if, for
example, we want to vary their size at runtime). In this case, we
allocate the object on the heap and keep a pointer to it.</p>

<p>Once we start working with heap objects, ownership becomes even more
important: unlike stack objects, which get automatically destroyed when
their stack frame gets popped, heap objects need to be explicitly
deleted. This responsibility should be with the <em>owner</em> of the object.</p>

<h3>Unique pointer</h3>

<p>A unique pointer (<code>std::unique_ptr</code>) is a wrapper around a raw pointer
which will automatically delete the heap object when it goes out of
scope itself:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">ptrBar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">();</span>
<span class="p">}</span><span class="w"> </span><span class="c1">// ptrBar goes out of scope =&gt; heap object gets deleted</span>
</pre></div>

<p>The above call to <code>make_unique</code> allocates an instance of Bar on the heap
and wraps the pointer to it into the unique pointer <code>ptrBar</code>. Now
<code>ptrBar</code> <em>owns</em> the object and as soon as ptrBar goes out of scope, the
heap object is also deleted.</p>

<p>Unique pointers cannot be copied, so we can never accidentally have more
than one single <code>unique_ptr</code> pointing to the same heap object:</p>
<div class="highlight"><pre><span/><span class="k">auto</span><span class="w"> </span><span class="n">ptrBar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">();</span>
<span class="p">...</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ptrBar2</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ptrBar</span><span class="p">;</span><span class="w"> </span><span class="c1">// Won't compile</span>
</pre></div>

<p>Of course, if we <em>really</em> want to, we can get the raw pointer out of
<code>ptrBar</code> using <code>get()</code> and we can initialize a <code>unique_ptr</code> from a raw
pointer -</p>
<div class="highlight"><pre><span/><span class="c1">// Please don't do this</span>
<span class="n">std</span><span class="o">::</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ptrBar2</span><span class="p">(</span><span class="n">ptrBar</span><span class="p">.</span><span class="n">get</span><span class="p">())</span>
</pre></div>

<p>but this is very bad - now both pointers think they have sole ownership
of the resource, and as soon as one goes out of scope, using the other
one leads to undefined behavior. In general, the same way there are very
few good reasons to use raw pointers, there are very few good reasons to
call <code>get()</code> on a smart pointer.</p>

<h3>Shared pointer</h3>

<p>Sometimes, we do need to have several pointers pointing to the same heap
object. In this case, we can use shared pointers. Shared pointers
pointing to the same heap object keep a common reference count. Whenever
a new shared pointer is created for that particular heap object, the
reference count is incremented. Whenever a shared pointer for that heap
object goes out of scope, the reference count is decremented. Once the
last shared pointer goes out of scope, the heap object is deleted.</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">ptrBar1</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">    </span><span class="c1">// one pointer to a Bar object on the heap (ref count = 1)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">auto</span><span class="w"> </span><span class="n">ptrBar2</span><span class="p">(</span><span class="n">ptrBar1</span><span class="p">);</span>
<span class="w">        </span><span class="c1">// second shared pointer (ref count = 2)</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="c1">// ptrBar2 goes out of scope (ref count = 1)</span>
<span class="p">}</span>
<span class="c1">// ptrBar1 goes out of scope (ref count = 0) =&gt; heap object is deleted</span>
</pre></div>

<p>Shared pointers incur a bit more overhead than unique pointers -
reference counting needs to be atomic to account for multi-threaded
environments, which comes with a runtime cost. The reference count
itself also needs to be stored somewhere, which is a small space cost.
Unique pointers don't have these time and space costs since they don't
need to count references - there is always only one pointer to the
object.</p>

<p>Costs aside, shared pointers also don't make the ownership clear -
there are several instances <q>owning</q> the heap resource at the same
time, which can potentially alter it and step on each other's toes. In
general, prefer unique pointers to shared pointers whenever possible.</p>

<h3>Raw pointer</h3>

<p>Avoid using raw pointers. Raw pointers don't express ownership, so they
don't offer the same guarantees that a) the resource pointed to gets
properly cleaned up and b) the resource pointed to is still valid at a
given time. This leads to dereferencing invalid memory and
double-deletes (trying to free the same heap object multiple times),
which means undefined behavior. Also, don't mix smart and raw
pointers - the smart pointers will keep doing their job happily, with
the potential of making the raw pointers invalid.</p>

<h3>COM pointers</h3>

<p>On Windows, COM uses a different reference counting mechanism: the base
<code>IUnknown</code> interface declares <code>AddRef</code> and <code>Release</code> methods, which
implementations are expected to use to keep track of the reference
count. <code>CComPtr</code> (in ATL) and <code>ComPtr</code> (in WRL) are the COM smart
pointers. They call <code>AddRef</code> and <code>Release</code> on the owned object, and the
owned object is supposed to delete itself once its reference count drops
to 0. Note that COM uses a slightly different mechanism than the
standard library shared pointers -instead of the smart pointer keeping
track of the reference count in the control block and deleting the
object once the last reference goes away, COM objects are expected to
keep track of their reference count themselves through the <code>AddRef</code> and
<code>Release</code> methods and self-delete when the last reference goes away
(through <code>Release</code> call). The COM smart pointers only need to call
<code>Release</code> when they go out of scope.</p>

<p>It's not a good idea to have both standard library and COM pointers
point to the same object, as each might decide to delete the object at
different times -<code>shared_ptr</code> looks at the <code>shared_ptr</code> refcount while
COM objects look at their internal reference count. So a <code>shared_ptr</code>
might decide to delete an object while a <code>ComPtr</code> still expects it to be
valid or vice-versa. In general, when working with COM objects, use COM
smart pointers.</p>

<h3>auto_ptr</h3>

<p><code>auto_ptr</code> is a deprecated smart pointer. Unless working with an old
compiler and standard library, use <code>unique_ptr</code> or <code>shared_ptr</code> instead.</p>

<h3>Other smart pointers</h3>

<p>Old code bases might have custom smart pointer implementations, for the
simple fact that automatic memory management is always a good idea, and
there is C++ code that predates the introduction of smart pointers into
the standard library. When interoperating with legacy code, use whatever
works, but when writing new code, do prefer standard library smart
pointers to homebrewed ones.</p>

<h3>Summary</h3>

<p>In summary, when creating objects:</p>

<ol>
<li>Create them on the stack if feasible (note that standard library
types like <code>std::vector</code> and <code>std::string</code> internally keep their
data on the heap, but they fit perfectly well on the stack, so you
don't need to create an <code>std::vector</code> on the heap just because you
are planning to store a lot of elements in it - the vector manages a
heap array internally already).</li>
<li>Use a <code>unique_ptr</code> when creating them on the heap, to make ownership
obvious.</li>
<li>Use a <code>shared_ptr</code> only when <code>unique_ptr</code> isn't sufficient (review
your design first, might be a design issue).</li>
<li>Use COM smart pointers like <code>CComPtr</code> when dealing with COM.</li>
<li>Don't use <code>auto_ptr</code> or other old constructs unless working with
legacy code/compiler.</li>
<li>Don't use raw pointers.</li>
</ol>

<h2>Passing Smart Pointers as Arguments</h2>

<p>We covered passing arguments and smart pointers. Now combining the two,
how do we pass heap objects as arguments? Turns out Herb Sutter has <a href="http://bit.ly/227Na5c">a
great post</a> on this exact topic on his blog. I
can't hope to explain better than him, so go read his post. I will try
to summarize:</p>

<h3>Pass by reference the pointed-to type</h3>

<p>Rather than forcing callers to use <code>unique_ptr</code> or <code>shared_ptr</code> by
specifying the smart pointer type (which makes assumptions about
ownership), just ask for a reference to the pointed-to-type:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Bar</span><span class="o">&amp;</span><span class="w"> </span><span class="n">bar</span><span class="p">);</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">ptrBar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">    </span><span class="n">do_stuff</span><span class="p">(</span><span class="o">*</span><span class="n">ptrBar</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Herb also mentions raw pointer to the underlying type if the argument
can be null, but as I mentioned above, I'd rather stick to references
and discourage use of raw pointers as a general rule of thumb.</p>

<h3>Pass smart pointer by value</h3>

<p>Passing a <code>unique_ptr</code> by value implies a sink argument - since a
<code>unique_ptr</code> cannot be copied, it has to be <code>std::move</code>'d in.
Interestingly, Scott Meyers has <a href="http://bit.ly/1WgkvEh">a post</a> on his
blog where he disagrees with this and argues that arguments of move-only
types should be specified as <code>&amp;&amp;</code>:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="n">unique_ptr</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;&amp;&amp;</span><span class="w"> </span><span class="n">ptrBar</span><span class="p">);</span><span class="w"> </span><span class="c1">// sink</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">ptrBar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_unique</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">    </span><span class="n">do_stuff</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">ptrBar</span><span class="p">));</span>
<span class="p">}</span>
</pre></div>

<p>Passing a <code>shared_ptr</code> by value implies the function wants to partake in
the ownership - in other words, will keep somewhere a reference to the
object after the function returns, but unlike the above <code>unique_ptr</code>
example, it won't have exclusive ownership of the resource:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ptrBar</span><span class="p">);</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">auto</span><span class="w"> </span><span class="n">ptrBar</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="p">();</span>
<span class="w">    </span><span class="n">do_stuff</span><span class="p">(</span><span class="n">ptrBar</span><span class="p">);</span><span class="w"> </span><span class="c1">// copy-constructs another shared_ptr which shares ownership of the heap object</span>
<span class="p">}</span>
</pre></div>

<h3>Pass smart pointer by reference</h3>

<p>Only expect a smart pointer by non-const reference if the function is
going to modify the smart pointer itself (eg. by making it point to a
different object). In my experience, this is a rare occurrence.</p>
<div class="highlight"><pre><span/><span class="c1">// Implies this function modifies the pointer itself.</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">ptrBar</span><span class="p">);</span>
</pre></div>

<p>There is no good reason to expect a <code>const&amp;</code> to a <code>unique_ptr</code>, just
reference the underlying type:</p>
<div class="highlight"><pre><span/><span class="c1">// void do_stuff(const unique_ptr&lt;Bar&gt;&amp; ptrBar);</span>
<span class="c1">// No reason to use the above as opposed to</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Bar</span><span class="o">&amp;</span><span class="w"> </span><span class="n">bar</span><span class="p">);</span>
</pre></div>

<p>Expect <code>const&amp;</code> to <code>shared_ptr</code> only if the function <em>might</em> create a
copy of the smart pointer. If the function would never create a copy of
the pointer, simply use <code>&amp;</code> to underlying type. If the function would
always copy the pointer, expect <code>shared_ptr</code> by value.</p>
<div class="highlight"><pre><span/><span class="c1">// Might or might not share ownership</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">ptrBar</span><span class="p">);</span>

<span class="c1">// Will never share ownership</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">Bar</span><span class="o">&amp;</span><span class="w"> </span><span class="n">bar</span><span class="p">);</span>

<span class="c1">// Will always share ownership</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">do_stuff</span><span class="p">(</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">Bar</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ptrBar</span><span class="p">);</span>
</pre></div>

<h3>Summary</h3>

<p>A summary of the summary:</p>

<ol>
<li>Take argument by <code>&amp;</code> to underlying type if you only care about the
heap object, not about the pointer.</li>
<li>Take <code>unqiue_ptr</code> by <code>&amp;&amp;</code> to transfer ownership.</li>
<li>Take <code>shared_ptr</code> argument by value to partake in ownership.</li>
<li>Take smart pointer by (non-const) reference only if you are going to
modify the smart pointer itself.</li>
<li>No need for <code>const&amp;</code> to <code>unique_ptr</code> (just take <code>&amp;</code> to underlying
type)</li>
<li>Take <code>const&amp;</code> to <code>shared_ptr</code> only if unknown whether function wants
ownership (take by <code>&amp;</code> to underlying type if function never wants
ownership, <code>shared_ptr</code> by value if function always wants
ownership).</li>
</ol>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>Move constructors can be implicitly declared by the compiler if
certain conditions are met, see
<a href="http://en.cppreference.com/w/cpp/language/move_constructor#Implicitly-declared_move_constructor">here</a>
for details. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Fri, 11 Mar 2016 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/01/07/clean-code-part-2.html</link>
      <guid>https://vladris.com/blog/2016/01/07/clean-code-part-2.html</guid>
      <title><![CDATA[Clean Code - Part 2]]></title>
      <description><![CDATA[<h1>Clean Code - Part 2</h1>

<p>In <a href="https://vladris.com/blog/2016/01/07/clean-code-part-2.html">Part 1</a> I
talked about writing less code and writing simple code. In this post I will
cover writing stateless code and writing readable code.</p>

<h2>Write Stateless Code</h2>

<blockquote>
<p>AÂ <strong>pure function</strong>Â is aÂ <strong>function</strong>Â where the return value is
only determined by its input values, without observable side effects.
This is how <strong>functions</strong> in math work: <code>Math.cos(x)</code> will, for the
same value of <code>x</code>, always return the same result.</p>

<p><em>Source:</em>
<a href="http://www.sitepoint.com/functional-programming-pure-functions/">SitePoint</a></p>
</blockquote>

<p>Things break when a program gets into a <q>bad state</q>. There are a
couple of ways to make this less likely to happen: making data immutable
and writing functions that don't have side-effects (<em>pure</em> functions).</p>

<h3>Immutable data</h3>

<p>If something shouldn't change, mark it as immutable and let the
compiler enforce that. A good rule of thumb is to mark things as <code>const</code>
(<code>const&amp;</code>, <code>const*</code> etc.) and/or <code>readonly</code> by default, and make them
mutable only when truly needed<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>.</p>

<p>A simple example:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">StringUtil</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="w"> </span><span class="nf">Concat1</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">str1</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">str2</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">str1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">str2</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="w"> </span><span class="nf">Concat2</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">str1</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">str2</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">str1</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">str2</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>Both <code>StringUtil::Concat1</code> and <code>StringUtil::Concat2</code> return the same
thing for the same input, the difference being that <code>Concat2</code>, as
opposed to <code>Concat1</code>, modifies its first argument. In a bigger function,
such a change might be introduced accidentally and have unexpected
consequences down the line.</p>

<p>A simple way to address this is by explicitly marking the arguments as
<code>const</code>:</p>
<div class="highlight"><pre><span/><span class="k">struct</span><span class="w"> </span><span class="nc">StringUtil</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="w"> </span><span class="nf">Concat1</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">str1</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">str2</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">         </span><span class="k">return</span><span class="w"> </span><span class="n">str1</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">str2</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">static</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="w"> </span><span class="nf">Concat2</span><span class="p">(</span><span class="k">const</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">str1</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="w"> </span><span class="n">str2</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">         </span><span class="k">return</span><span class="w"> </span><span class="n">str1</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">str2</span><span class="p">);</span><span class="w"> </span><span class="c1">// Won't compile - can't call append on str1</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>In this case, <code>Concat2</code> won't compile, so we can rely on the compiler
to eliminate this type of unintended behavior.</p>

<p>Another example: a simple <code>UpCase</code> function which calls <code>toupper</code> on
each character of the given string, upcasing it in place:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">UpCase</span><span class="p">(</span><span class="kt">char</span><span class="w"> </span><span class="o">*</span><span class="n">string</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">string</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="o">*</span><span class="n">string</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">toupper</span><span class="p">(</span><span class="o">*</span><span class="n">string</span><span class="p">);</span>
<span class="w">        </span><span class="n">string</span><span class="o">++</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">};</span>
</pre></div>

<p>Calling it with</p>
<div class="highlight"><pre><span/><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">myString</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Foo"</span><span class="p">;</span>
<span class="p">...</span>
<span class="n">UpCase</span><span class="p">(</span><span class="n">myString</span><span class="p">);</span>
</pre></div>

<p>will lead to a crash at runtime - the function will try to call
<code>toupper</code> on the characters of <code>myString</code>. The problem is that
<code>myString</code> is a <code>char*</code> to a string literal which gets compiled into the
read-only data segment of the binary. This cannot be modified.</p>

<p>To catch this type of errors at compile-time, we again only need to mark
the immutable data as such:</p>
<div class="highlight"><pre><span/><span class="k">const</span><span class="w"> </span><span class="kt">char</span><span class="o">*</span><span class="w"> </span><span class="n">myString</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Foo"</span><span class="p">;</span>
<span class="p">...</span>
<span class="n">UpCase</span><span class="p">(</span><span class="n">myString</span><span class="p">);</span><span class="w"> </span><span class="c1">// Won't compile - can't call UpCase on myString</span>
</pre></div>

<p>In contrast with the previous example, the argument to <code>UpCase</code> is
mutable by design (the API is modifying the string in-place), but
marking <code>myString</code> as <code>const</code> tells the complier this is non-mutable
data, so it can't be used with this API.</p>

<h3>Pure functions</h3>

<p>Another way to reduce states is to use pure functions. Unfortunately
there isn't a lot of syntax-level support for this in C++ and C# (C++
supports <code>const</code> member functions, which guarantee at compile time that
calling the member function on an instance of the type won't change the
attributes of that instance)<sup id="fnref2"><a href="#fn2" rel="footnote">2</a></sup></p>

<p>This goes back to the recommendation from Part 1 of using generic
algorithms and predicates rather than implementing raw loops. In many
cases, traversal state is encapsulated in the library algorithm or in an
iterator, and predicates ideally don't have side-effects.</p>
<div class="highlight"><pre><span/><span class="kt">var</span><span class="w"> </span><span class="n">squares</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span>
<span class="w">                </span><span class="n">Where</span><span class="p">(</span><span class="n">number</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">).</span>
<span class="w">                </span><span class="n">Select</span><span class="p">(</span><span class="n">number</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">number</span><span class="p">);</span>
</pre></div>

<p>Above code (also from Part 1) doesn't hold any state: traversal is
handled by the Linq methods, the predicates are pure.</p>

<p>In general, try to encapsulate state in parts of the code built to
manage state, and keep the rest stateless. Note that immutable data and
pure functions are also an advantage in concurrent applications, since
they can't generate race conditions.</p>

<p>Key takeaways:</p>

<ul>
<li>Prefer pure functions to stateful functions and, if state is needed,
keep it contained</li>
<li>By default mark everything as <code>const</code> (or <code>readonly</code>), and only
remove the constraint when mutability is explicitly needed</li>
</ul>

<h2>Write Readable Code</h2>

<blockquote>
<p>In computer science, theÂ <strong>expressiveÂ power</strong> (also called
<strong>expressiveness</strong> or expressivity) of a language is the breadth of
ideas that can be represented and communicated in that language
[...]</p>

<ul>
<li>regardless of ease (theoretical expressivity)</li>
<li><strong>concisely and readily</strong> (practical expressivity)</li>
</ul>

<p><em>Source:</em>
<a href="https://en.wikipedia.org/wiki/Expressive_power_(computer_science)">Wikipedia</a></p>
</blockquote>

<p>Code is read many more times than it is written/modified, so it should
be optimized for readability. What I mean by this is making the intent
of the code clear at a glance - this includes giving good descriptive
names to variables, functions, and types, adding useful comments where
appropriate (a comment should describe what the code does if it is
non-obvious; a comment like <code>foo(); // calls foo()</code> is not a useful
comment), and in general structure the code for easy reading.</p>

<p>For a counterexample, think back on a piece of code you read that
elicited a WTF. That's the kind of code you don't want to write.</p>

<p>I won't insist much here, since there are countless books and industry
best practices for improving code readability.</p>

<p>Another way to make the code more readable is to have a good knowledge
of the language you are using. The strength of a language lies in its
particularities, so use them whenever appropriate. This means writing
<a href="http://stackoverflow.com/questions/84102/what-is-idiomatic-code">idiomatic
code</a>,
which implies knowledge of the language idioms. Don't write C++ code
like C code, write it like C++ code. Don't write C# code as C++, write
it as C# etc.</p>

<p>Also, keep up to date on the language. Language syntax evolves to
address needs, so in general modern syntax introduces simpler, better
ways to implement things than old syntax. Take object allocation and
initialization in C++ as an example:</p>
<div class="highlight"><pre><span/><span class="n">Foo</span><span class="o">*</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="n">Foo</span><span class="o">*</span><span class="p">)</span><span class="n">malloc</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">Foo</span><span class="p">));</span>
<span class="n">init</span><span class="p">(</span><span class="n">foo</span><span class="p">);</span>
<span class="p">...</span>
<span class="n">deinit</span><span class="p">(</span><span class="n">foo</span><span class="p">);</span>
<span class="n">free</span><span class="p">(</span><span class="n">foo</span><span class="p">);</span>
</pre></div>

<p>This is the C way of allocating and initializing a structure on the
heap, then deinitializing and freeing it. Allocation and initialization
are separate steps, with opportunity to leak both memory (by omitting
the <code>free</code> call) and managed resources (by omitting the <code>deinit</code> call).
Not to mention opportunity to end up with an initialized struct (by
omitting the <code>init</code> call), or accidental double-initialization,
double-deinitialization, double-free etc.</p>

<p>C++ introduced classes, and the following syntax:</p>
<div class="highlight"><pre><span/><span class="n">Foo</span><span class="o">*</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Foo</span><span class="p">();</span>
<span class="p">...</span>
<span class="k">delete</span><span class="w"> </span><span class="n">foo</span><span class="p">;</span>
</pre></div>

<p><code>new</code> both allocates memory and calls the constructor, while <code>delete</code>
calls the destructor then releases the memory. Many of the problems in
the C example go away, but there is still the problem of leaking the
resource by omitting the <code>delete</code> call, and the issue of calling
<code>delete</code> twice on the same memory address.</p>

<p>To address these issues, smart pointers were introduced in the language:</p>
<div class="highlight"><pre><span/><span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="w"> </span><span class="n">foo</span><span class="p">(</span><span class="k">new</span><span class="w"> </span><span class="n">Foo</span><span class="p">());</span>
</pre></div>

<p>Smart pointers encapsulate reference counting (how many <code>shared_ptr</code>
objects point to the same memory address), and automatically release the
resource when the last reference goes away. This gets rid of most
problems, but there is an even better way of allocating heap objects:</p>
<div class="highlight"><pre><span/><span class="k">auto</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">Foo</span><span class="o">&gt;</span><span class="p">();</span>
</pre></div>

<p><code>make_shared</code> has the advantage of improved performance, by allocating
memory in a single operation for both the object and the shared
pointer's own control block<sup id="fnref3"><a href="#fn3" rel="footnote">3</a></sup>. It also prevents leaks due to
interleaving<sup id="fnref4"><a href="#fn4" rel="footnote">4</a></sup>. So as the C++ language evolved, new constructs
appeared to address potential problems. Keeping up to date with these
updates, and incorporating them into your code will reduce the
opportunity for bugs, make the code more concise, and thus more
readable.</p>

<h3>Beautiful Code</h3>

<p>I encourage you to not stop at writing <em>working</em> code, rather strive to
write <em>beautiful</em> code. I have the following quote from <a href="http://www.goodreads.com/book/show/5608045-apprenticeship-patterns">Apprenticeship
Patterns</a>
on the wall behind my monitors, so I can see it while I work:</p>

<blockquote>
<p>There's always a better/faster/smarter way to do what you're
currently doing</p>
</blockquote>

<p>So don't stop as soon as something works, ask yourself <em>is this the
best way to implement this?</em></p>

<p>Key takeaways:</p>

<ul>
<li>Come up with good names</li>
<li>Write meaningful comments</li>
<li>Keep up to date with your language</li>
<li>Don't just write working code, write beautiful code.</li>
</ul>

<h2>Epilogue</h2>

<p>As I was working on putting together the talk that inspired this post, I
realized there are a few more rules of thumb which I could cover. The
current working draft is:</p>

<ul>
<li>Write safe code</li>
<li>Write leakproof code</li>
<li>Write responsive code</li>
<li>Write testable code</li>
</ul>

<p>Sometime in the future I hope to continue the series with the above, in
the meantime, I'll leave you with this one sentence summary:</p>

<blockquote>
<p>Always code as if the person who ends up maintaining your code is a
violent psychopath who knows where you live</p>

<p><em>Source:</em> <a href="http://blog.codinghorror.com/coding-for-violent-psychopaths/">Coding
Horror</a></p>
</blockquote>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>At the time of this writing, there is an <a href="https://github.com/dotnet/roslyn/issues/7626">active
proposals</a> to extend
the C# language with an <code>immutable</code> keyword. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

<li id="fn2">
<p>C# has a <code>PureAttribue</code> in the <code>System.Diagnostics.Contracts</code>
namespace (purity not compiler-enforced) and there is an <a href="https://github.com/dotnet/roslyn/issues/7561">active
proposal</a> to add a
keyword for it too. <a href="#fnref2" rev="footnote">↩</a></p>
</li>

<li id="fn3">
<p>This is a non-binding requirement in the standard, meaning a
standard library implementation doesn't <em>have to</em> do this, but most
implementations will. You can read more about it
<a href="http://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared">here</a>. <a href="#fnref3" rev="footnote">↩</a></p>
</li>

<li id="fn4">
<p>Interleaving occurs since call order is not guaranteed. For
example, in <code>bar(std::share_ptr&lt;Foo&gt;(new foo()), baz())</code>, there is
no guarantee that call order will be <code>new foo()</code>, then the shared
pointer's constructor, then <code>baz()</code>. Calls might get interleaved
and executed as <code>new foo()</code>, then <code>baz()</code>, then the shared pointer
constructor, in which case an exception thrown by <code>baz()</code> would leak
the newly allocated <code>Foo</code> object, since the shared pointer didn't
get ownership of it yet. <a href="#fnref4" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Thu, 07 Jan 2016 00:00:00 -0800</pubDate>
    </item>

    <item>
      <link>https://vladris.com/blog/2016/01/04/clean-code-part-1.html</link>
      <guid>https://vladris.com/blog/2016/01/04/clean-code-part-1.html</guid>
      <title><![CDATA[Clean Code - Part 1]]></title>
      <description><![CDATA[<h1>Clean Code - Part 1</h1>

<p>These posts are based on a Clean Code talk I did for my team a few
months ago, which, in turn, was inspired by the advice I gave to some of
our summer interns as four rules of thumb for writing cleaner code:</p>

<ul>
<li>Write less code</li>
<li>Write simple code</li>
<li>Write stateless code</li>
<li>Write readable code</li>
</ul>

<p>I will cover the first two points in this post and the remaining two in
Part 2. I'm talking about C++ and C# throughout, but most of this
should be applicable to any object-oriented or multi-paradigm language.</p>

<h2>Write Less Code</h2>

<blockquote>
<p>The number of defects found in open source projects was 0.45
defects/1,000 lines of code, while the industry's average is around 1
defect perÂ 1,000 lines of code for companies not using automated
testing such as static analysis.</p>

<p><em>Source:</em>
<a href="http://www.infoq.com/news/2012/03/Defects-Open-Source-Commercial">InfoQ</a></p>
</blockquote>

<p>A great way to have fewer bugs is to have fewer lines of code! What I
mean by this is that churning out many lines of code is by no means a
measure of productivity yet, unfortunately, most developers still feel
great when, at the end of the day, we wrote <em>insert high number</em> LoC.</p>

<h3>How to write less code?</h3>

<p>Two points to keep in mind: first, don't reinvent the wheel - don't
write code if there is an existing library, internal to your company or
open-source, that already does what needs to be done. Case in point, we
refactored some code for a project (C#), extracted some interfaces,
componentized things, and wrote a bunch of unit tests. All of this was
great, except we ended up with a bunch of handcrafted stub classes: for</p>
<div class="highlight"><pre><span/><span class="k">interface</span><span class="w"> </span><span class="n">IMyComponent</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">void</span><span class="w"> </span><span class="nf">Foo</span><span class="p">();</span>
<span class="w">    </span><span class="kt">int</span><span class="w"> </span><span class="nf">Bar</span><span class="p">();</span>
<span class="w">    </span><span class="k">void</span><span class="w"> </span><span class="nf">Baz</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>we had</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">MyComponentStub</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">IMyComponent</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Foo</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="nf">Bar</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">Baz</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
<span class="p">...</span>
<span class="kt">var</span><span class="w"> </span><span class="n">myComponentStub</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">MyComponentStub</span><span class="p">();</span>
</pre></div>

<p>and so on. Implementing these stubs was tedious, needless work - we
integrated <a href="https://github.com/Moq/moq4">Moq</a> , a mocking library, and
the above code turned into:</p>
<div class="highlight"><pre><span/><span class="k">using</span><span class="w"> </span><span class="nn">Moq</span><span class="p">;</span>
<span class="p">...</span>
<span class="kt">var</span><span class="w"> </span><span class="n">myComponentStub</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Mock</span><span class="p">.</span><span class="n">Of</span><span class="o">&lt;</span><span class="n">IMyComponent</span><span class="o">&gt;</span><span class="p">();</span>
</pre></div>

<p>Moq uses reflection to stub out interfaces at run-time, so simply
adopting the library helped us get rid of a lot of code.</p>

<p>The second way to write less code is to know the standard library of
your language of choice. Many times, a block of code can be replaced
with a simple library call. For C++, pay particular attention to the STL
<code>&lt;algorithm&gt;</code> header and for C#, <code>System.Linq</code>. Both contain many of
useful algorithms which can replace a lot of code.</p>

<p>I also recommend watching Sean Parent's <a href="https://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning">C++
Seasoning</a>
talk, one of the best tech talks I've seen. The example he gives in the
talk (from the Chrome codebase) shows how a couple of lines of STL code
can be used instead of a whole convoluted function:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">PanelBar::RepositionExpandedPanels</span><span class="p">(</span><span class="n">Panel</span><span class="o">*</span><span class="w"> </span><span class="n">fixed_panel</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">  </span><span class="n">CHECK</span><span class="p">(</span><span class="n">fixed_panel</span><span class="p">);</span>

<span class="w">  </span><span class="c1">// First, find the index of the fixed panel.</span>
<span class="w">  </span><span class="kt">int</span><span class="w"> </span><span class="n">fixed_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">GetPanelIndex</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">fixed_panel</span><span class="p">);</span>
<span class="w">  </span><span class="n">CHECK_LT</span><span class="p">(</span><span class="n">fixed_index</span><span class="p">,</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>

<span class="w">  </span><span class="c1">// Next, check if the panel has moved to the other side of another panel.</span>
<span class="w">  </span><span class="k">const</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">center_x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fixed_panel</span><span class="o">-&gt;</span><span class="n">cur_panel_center</span><span class="p">();</span>
<span class="w">  </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">size_t</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">size</span><span class="p">();</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">Panel</span><span class="o">*</span><span class="w"> </span><span class="n">panel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">get</span><span class="p">();</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">center_x</span><span class="w"> </span><span class="o">&lt;=</span><span class="w"> </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">cur_panel_center</span><span class="p">()</span><span class="w"> </span><span class="o">||</span>
<span class="w">        </span><span class="n">i</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="mi">1</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">panel</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">fixed_panel</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">        </span><span class="c1">// If it has, then we reorder the panels.</span>
<span class="w">        </span><span class="n">ref_ptr</span><span class="o">&lt;</span><span class="n">Panel</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">[</span><span class="n">fixed_index</span><span class="p">];</span>
<span class="w">        </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">fixed_index</span><span class="p">);</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">size</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">          </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">i</span><span class="p">,</span><span class="w"> </span><span class="n">ref</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span>
<span class="w">          </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">ref</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">      </span><span class="p">}</span>
<span class="w">    </span><span class="k">break</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="c1">// Find the total width of the panels to the left of the fixed panel.</span>
<span class="w">  </span><span class="kt">int</span><span class="w"> </span><span class="n">total_width</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">  </span><span class="n">fixed_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">-1</span><span class="p">;</span>
<span class="w">  </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">i</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">size</span><span class="p">());</span><span class="w"> </span><span class="o">++</span><span class="n">i</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">Panel</span><span class="o">*</span><span class="w"> </span><span class="n">panel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">get</span><span class="p">();</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">panel</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">fixed_panel</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="n">fixed_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">i</span><span class="p">;</span>
<span class="w">      </span><span class="k">break</span><span class="p">;</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="n">total_width</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">panel_width</span><span class="p">();</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="n">CHECK_NE</span><span class="p">(</span><span class="n">fixed_index</span><span class="p">,</span><span class="w"> </span><span class="mi">-1</span><span class="p">);</span>
<span class="w">  </span><span class="kt">int</span><span class="w"> </span><span class="n">new_fixed_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">fixed_index</span><span class="p">;</span>

<span class="w">  </span><span class="c1">// Move panels over to the right of the fixed panel until all of the ones</span>
<span class="w">  </span><span class="c1">// on the left will fit.</span>
<span class="w">  </span><span class="kt">int</span><span class="w"> </span><span class="n">avail_width</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">max</span><span class="p">(</span><span class="n">fixed_panel</span><span class="o">-&gt;</span><span class="n">cur_panel_left</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">kBarPadding</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w">  </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">total_width</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">avail_width</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">new_fixed_index</span><span class="o">--</span><span class="p">;</span>
<span class="w">    </span><span class="n">CHECK_GE</span><span class="p">(</span><span class="n">new_fixed_index</span><span class="p">,</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>
<span class="w">    </span><span class="n">total_width</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">[</span><span class="n">new_fixed_index</span><span class="p">]</span><span class="o">-&gt;</span><span class="n">panel_width</span><span class="p">();</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="c1">// Reorder the fixed panel if its index changed.</span>
<span class="w">  </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">new_fixed_index</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">fixed_index</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">Panels</span><span class="o">::</span><span class="n">iterator</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">fixed_index</span><span class="p">;</span>
<span class="w">    </span><span class="n">ref_ptr</span><span class="o">&lt;</span><span class="n">Panel</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="n">it</span><span class="p">;</span>
<span class="w">    </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">it</span><span class="p">);</span>
<span class="w">    </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">new_fixed_index</span><span class="p">,</span><span class="w"> </span><span class="n">ref</span><span class="p">);</span>
<span class="w">    </span><span class="n">fixed_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">new_fixed_index</span><span class="p">;</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="c1">// Now find the width of the panels to the right, and move them to the</span>
<span class="w">  </span><span class="c1">// left as needed.</span>
<span class="w">  </span><span class="n">total_width</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span>
<span class="w">  </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">Panels</span><span class="o">::</span><span class="n">iterator</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">fixed_index</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w">          </span><span class="n">it</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">end</span><span class="p">();</span><span class="w"> </span><span class="o">++</span><span class="n">it</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">total_width</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">it</span><span class="p">)</span><span class="o">-&gt;</span><span class="n">panel_width</span><span class="p">();</span>
<span class="w">  </span><span class="p">}</span>
<span class="w">  </span><span class="n">avail_width</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">max</span><span class="p">(</span><span class="n">wm_</span><span class="o">-&gt;</span><span class="n">width</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="p">(</span><span class="n">fixed_panel</span><span class="o">-&gt;</span><span class="n">cur_right</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">kBarPadding</span><span class="p">),</span><span class="w"> </span><span class="mi">0</span><span class="p">);</span>

<span class="w">  </span><span class="k">while</span><span class="w"> </span><span class="p">(</span><span class="n">total_width</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">avail_width</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">new_fixed_index</span><span class="o">++</span><span class="p">;</span>
<span class="w">    </span><span class="n">CHECK_LT</span><span class="p">(</span><span class="n">new_fixed_index</span><span class="p">,</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>
<span class="w">    </span><span class="n">total_width</span><span class="w"> </span><span class="o">-=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">[</span><span class="n">new_fixed_index</span><span class="p">]</span><span class="o">-&gt;</span><span class="n">panel_width</span><span class="p">();</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="c1">// Do the reordering again.</span>
<span class="w">  </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">new_fixed_index</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">fixed_index</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">Panels</span><span class="o">::</span><span class="n">iterator</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">fixed_index</span><span class="p">;</span>
<span class="w">    </span><span class="n">ref_ptr</span><span class="o">&lt;</span><span class="n">Panel</span><span class="o">&gt;</span><span class="w"> </span><span class="n">ref</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">*</span><span class="n">it</span><span class="p">;</span>
<span class="w">    </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">erase</span><span class="p">(</span><span class="n">it</span><span class="p">);</span>
<span class="w">    </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">new_fixed_index</span><span class="p">,</span><span class="w"> </span><span class="n">ref</span><span class="p">);</span>
<span class="w">    </span><span class="n">fixed_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">new_fixed_index</span><span class="p">;</span>
<span class="w">  </span><span class="p">}</span>

<span class="w">  </span><span class="c1">// Finally, push panels to the left and the right so they don't overlap.</span>
<span class="w">  </span><span class="kt">int</span><span class="w"> </span><span class="n">boundary</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">[</span><span class="n">fixed_index</span><span class="p">]</span><span class="o">-&gt;</span><span class="n">cur_panel_left</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">kBarPadding</span><span class="p">;</span>
<span class="w">  </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">Panels</span><span class="o">::</span><span class="n">reverse_iterator</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span>
<span class="w">       </span><span class="c1">// Start at the panel to the left of 'new_fixed_index'.</span>
<span class="w">       </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">rbegin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">size</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">new_fixed_index</span><span class="p">);</span>
<span class="w">       </span><span class="n">it</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">rend</span><span class="p">();</span><span class="w"> </span><span class="o">++</span><span class="n">it</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">Panel</span><span class="o">*</span><span class="w"> </span><span class="n">panel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">it</span><span class="o">-&gt;</span><span class="n">get</span><span class="p">();</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">cur_right</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">boundary</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">Move</span><span class="p">(</span><span class="n">boundary</span><span class="p">,</span><span class="w"> </span><span class="n">kAnimMs</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">cur_panel_left</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">Move</span><span class="p">(</span><span class="n">min</span><span class="p">(</span><span class="n">boundary</span><span class="p">,</span><span class="w"> </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">panel_width</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">kBarPadding</span><span class="p">),</span><span class="w"> </span><span class="n">kAnimMs</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="n">boundary</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">cur_panel_left</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">kBarPadding</span><span class="p">;</span>
<span class="w">  </span><span class="p">}</span>
<span class="w">  </span><span class="n">boundary</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">[</span><span class="n">fixed_index</span><span class="p">]</span><span class="o">-&gt;</span><span class="n">cur_right</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">kBarPadding</span><span class="p">;</span>

<span class="w">  </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="n">Panels</span><span class="o">::</span><span class="n">iterator</span><span class="w"> </span><span class="n">it</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">begin</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">new_fixed_index</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">;</span>
<span class="w">       </span><span class="n">it</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">end</span><span class="p">();</span><span class="w"> </span><span class="o">++</span><span class="n">it</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">    </span><span class="n">Panel</span><span class="o">*</span><span class="w"> </span><span class="n">panel</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">it</span><span class="o">-&gt;</span><span class="n">get</span><span class="p">();</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">cur_panel_left</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">boundary</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">Move</span><span class="p">(</span><span class="n">boundary</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">panel_width</span><span class="p">(),</span><span class="w"> </span><span class="n">kAnimMs</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">cur_right</span><span class="p">()</span><span class="w"> </span><span class="o">&gt;</span><span class="w"> </span><span class="n">wm_</span><span class="o">-&gt;</span><span class="n">width</span><span class="p">())</span><span class="w"> </span><span class="p">{</span>
<span class="w">      </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">Move</span><span class="p">(</span><span class="n">max</span><span class="p">(</span><span class="n">boundary</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">panel_width</span><span class="p">(),</span>
<span class="w">                  </span><span class="n">wm_</span><span class="o">-&gt;</span><span class="n">width</span><span class="p">()</span><span class="w"> </span><span class="o">-</span><span class="w"> </span><span class="n">kBarPadding</span><span class="p">),</span>
<span class="w">                  </span><span class="n">kAnimMs</span><span class="p">);</span>
<span class="w">    </span><span class="p">}</span>
<span class="w">    </span><span class="n">boundary</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">panel</span><span class="o">-&gt;</span><span class="n">cur_right</span><span class="p">()</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">kBarPadding</span><span class="p">;</span>
<span class="w">  </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>becomes:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">PanelBar::RepositionExpandedPanels</span><span class="p">(</span><span class="n">Panel</span><span class="o">*</span><span class="w"> </span><span class="n">fixed_panel</span><span class="p">)</span><span class="w"> </span><span class="p">{</span>
<span class="w">  </span><span class="n">CHECK</span><span class="p">(</span><span class="n">fixed_panel</span><span class="p">);</span>

<span class="w">  </span><span class="c1">// First, find the index of the fixed panel.</span>
<span class="w">  </span><span class="kt">int</span><span class="w"> </span><span class="n">fixed_index</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">GetPanelIndex</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">,</span><span class="w"> </span><span class="o">*</span><span class="n">fixed_panel</span><span class="p">);</span>
<span class="w">  </span><span class="n">CHECK_LT</span><span class="p">(</span><span class="n">fixed_index</span><span class="p">,</span><span class="w"> </span><span class="n">expanded_panels_</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>

<span class="w">  </span><span class="c1">// Next, check if the panel has moved to the left side of another panel.</span>
<span class="w">  </span><span class="k">auto</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">begin</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">fixed_index</span><span class="p">;</span>
<span class="w">  </span><span class="k">auto</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">lower_bound</span><span class="p">(</span><span class="n">begin</span><span class="p">(</span><span class="n">expanded_panels_</span><span class="p">),</span><span class="w"> </span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="n">center_x</span><span class="p">,</span>
<span class="w">    </span><span class="p">[](</span><span class="k">const</span><span class="w"> </span><span class="n">ref_ptr</span><span class="o">&lt;</span><span class="n">Panel</span><span class="o">&gt;&amp;</span><span class="w"> </span><span class="n">e</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">x</span><span class="p">){</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">e</span><span class="o">-&gt;</span><span class="n">cur_panel_center</span><span class="p">()</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"> </span><span class="p">});</span>

<span class="w">  </span><span class="c1">// If it has, then we reorder the panels.</span>
<span class="w">  </span><span class="n">rotate</span><span class="p">(</span><span class="n">p</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="p">,</span><span class="w"> </span><span class="n">f</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>

<p>Code snippets borrowed from Sean Parent's slides, I highly recommend
watching the whole talk.</p>

<p>The key takeaway here is that there could be a standard library
implementation or an external module that can greatly simplify your work
and it's a good practice to always ask yourself <em><q>do I really need to
write this?</q></em></p>

<h2>Write Simple Code</h2>

<p>First, a few notes on cyclomatic complexity from Wikipedia:</p>

<blockquote>
<p>Cyclomatic complexityÂ is a software metric (measurement), used to
indicate theÂ complexityÂ of a program. It is a quantitative measure of
the number of linearly independent paths through a program's source
code.</p>

<p>The complexity M is then defined as</p>

<p><em>M = E â N + 2P</em></p>

<p>where</p>

<p><em>E = the number of edges of the graph, N = the number of nodes of
the graph, P = the number of connected components.</em></p>

<p><img src="https://vladris.com/blog/2016/01/04/cyclomatic_complexity.svg" alt="image"/></p>

<p>A control flow graph of a simple program. The program begins executing
at the red node, then enters a loop (group of three nodes immediately
below the red node). On exiting the loop, there is a conditional
statement (group below the loop), and finally the program exits at the
blue node. This graph has 9 edges, 8 nodes, and 1 connected component,
so the cyclomatic complexity of the program is 9 - 8 + 2 * 1 = 3.</p>

<p><em>Source:</em>
<a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity">Wikipedia</a></p>
</blockquote>

<p>The cyclomatic complexity of any piece of code should be minimized. This
can be achieved by avoiding branching, namely, whenever possible,
avoiding conditional statements and loops. Linear code is easier to read
and maintain, and provides less opportunities for bugs.</p>

<h3>Avoiding conditional statements</h3>

<p>One way to avoid conditional statements is to, whenever feasible, throw
exceptions instead of propagating errors through return values.</p>

<p>Here is an example of error code propagation through return values using
the Windows API's <code>HRESULT</code>:</p>
<div class="highlight"><pre><span/><span class="n">HRESULT</span><span class="w"> </span><span class="nf">foo</span><span class="p">();</span><span class="w"> </span><span class="c1">// Does some work and returns an HRESULT</span>
<span class="n">HRESULT</span><span class="w"> </span><span class="nf">bar</span><span class="p">();</span><span class="w"> </span><span class="c1">// Does some work and returns an HRESULT</span>

<span class="n">HRESULT</span><span class="w"> </span><span class="nf">baz</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">HRESULT</span><span class="w"> </span><span class="n">hr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">S_OK</span><span class="p">;</span>

<span class="w">    </span><span class="n">hr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo</span><span class="p">();</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">FAILED</span><span class="p">(</span><span class="n">hr</span><span class="p">))</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">hr</span><span class="p">;</span>

<span class="w">    </span><span class="n">hr</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">baz</span><span class="p">();</span>
<span class="w">    </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">FAILED</span><span class="p">(</span><span class="n">hr</span><span class="p">))</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">hr</span><span class="p">;</span>

<span class="w">    </span><span class="p">...</span><span class="w"> </span><span class="c1">// Some more work here which might fail</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">hr</span><span class="p">;</span>
<span class="p">}</span>

<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">SUCCEEDED</span><span class="p">(</span><span class="n">baz</span><span class="p">()))</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// :)</span>
<span class="p">}</span>
<span class="k">else</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// :(</span>
<span class="p">}</span>
</pre></div>

<p>This can be replaced with the more concise and much easier to read:</p>
<div class="highlight"><pre><span/><span class="kt">void</span><span class="w"> </span><span class="nf">foo</span><span class="p">();</span><span class="w"> </span><span class="c1">// Does some work, might throw</span>
<span class="kt">void</span><span class="w"> </span><span class="nf">bar</span><span class="p">();</span><span class="w"> </span><span class="c1">// Does some work, might throw</span>

<span class="kt">void</span><span class="w"> </span><span class="nf">baz</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">foo</span><span class="p">();</span>
<span class="w">    </span><span class="n">baz</span><span class="p">();</span>

<span class="w">    </span><span class="p">...</span><span class="w"> </span><span class="c1">// Some more work here which might fail (and throw)</span>
<span class="p">}</span>

<span class="k">try</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">baz</span><span class="p">();</span>
<span class="w">    </span><span class="c1">// :)</span>
<span class="p">}</span>
<span class="k">catch</span><span class="w"> </span><span class="p">(...)</span>
<span class="p">{</span>
<span class="w">    </span><span class="c1">// :(</span>
<span class="p">}</span>
</pre></div>

<p>Error code return values come from the old days when exceptions didn't
exist and make code harder to read. That being said, for C++
specifically, you should be careful about throwing exceptions across DLL
boundaries. In practice though, a lot of code in the shape of the above
example appears within the same executable for no good reason. If
cross-DLL boundary is a problem, I would actually recommend using
exceptions internally and switching to return codes at the public API
boundary.</p>

<p>Another way to avoid conditional statements is to use the <a href="https://en.wikipedia.org/wiki/Null_Object_pattern">Null Object
pattern</a> instead of
checking for null. For example, take an <code>IActivity</code> interface on which
we can log success or failure, and an <code>ActivityScope</code> which can retrieve
the current activity from a context:</p>
<div class="highlight"><pre><span/><span class="k">interface</span><span class="w"> </span><span class="n">IActivity</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">void</span><span class="w"> </span><span class="nf">LogSuccess</span><span class="p">();</span>
<span class="w">    </span><span class="k">void</span><span class="w"> </span><span class="nf">LogFailure</span><span class="p">();</span>
<span class="p">}</span>

<span class="k">class</span><span class="w"> </span><span class="nc">ActivityScope</span>
<span class="p">{</span>
<span class="w">    </span><span class="p">...</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">IActivity</span><span class="w"> </span><span class="nf">GetCurrentActivity</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">_context</span><span class="p">.</span><span class="n">HasCurrentActivity</span><span class="p">())</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="k">null</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">_context</span><span class="p">.</span><span class="n">GetActivity</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>With this implementation, all clients of the API have to make sure
<code>GetCurrentActivity()</code> returns an object as opposed to null. All callers
look like this:</p>
<div class="highlight"><pre><span/><span class="n">ActivityScope</span><span class="w"> </span><span class="n">activityScope</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">ActivityScope</span><span class="p">();</span>
<span class="n">activityScope</span><span class="p">.</span><span class="n">CreateActivity</span><span class="p">();</span>

<span class="p">...</span><span class="w"> </span><span class="c1">// Do a bunch of stuff</span>

<span class="kt">var</span><span class="w"> </span><span class="n">activity</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">activityScope</span><span class="p">.</span><span class="n">GetCurrentActivity</span><span class="p">();</span>
<span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">activity</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="k">null</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">activity</span><span class="p">.</span><span class="n">LogSuccess</span><span class="p">();</span>
<span class="p">}</span>
</pre></div>

<p>While there is a single <code>ActivityScope</code> implementation, there are
hundreds of calls to <code>GetCurrentActivity</code>, all coming with a boilerplate
null check. The Null Object alternative for this is to provide a
<code>NullActivity</code>, for which <code>LogSuccess</code> and <code>LogFailure</code> don't do
anything. <code>ActivityScope</code> can return <code>NullActivity</code> instead of null if
there is no <code>Activity</code> in the context:</p>
<div class="highlight"><pre><span/><span class="k">class</span><span class="w"> </span><span class="nc">NullActivity</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">IActivity</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">LogSuccess</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="k">void</span><span class="w"> </span><span class="nf">LogFailure</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="p">}</span>
<span class="p">}</span>

<span class="k">class</span><span class="w"> </span><span class="nc">ActivityScope</span>
<span class="p">{</span>
<span class="w">    </span><span class="p">...</span>
<span class="w">    </span><span class="k">private</span><span class="w"> </span><span class="k">static</span><span class="w"> </span><span class="n">NullActivity</span><span class="w"> </span><span class="n">_nullActivity</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">NullActivity</span><span class="p">();</span>

<span class="w">    </span><span class="k">public</span><span class="w"> </span><span class="n">IActivity</span><span class="w"> </span><span class="nf">GetCurrentActivity</span><span class="p">()</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="o">!</span><span class="n">_context</span><span class="p">.</span><span class="n">HasCurrentActivity</span><span class="p">())</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="k">return</span><span class="w"> </span><span class="n">_nullActivity</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">        </span><span class="k">return</span><span class="w"> </span><span class="n">_context</span><span class="p">.</span><span class="n">GetActivity</span><span class="p">();</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>

<p>Now callers don't need to worry about getting back a null, and can use
the API like this:</p>
<div class="highlight"><pre><span/><span class="n">activityScope</span><span class="p">.</span><span class="n">GetCurrentActivity</span><span class="p">().</span><span class="n">LogSuccess</span><span class="p">();</span>
</pre></div>

<p>Yet another way to reduce branching is when it used for mapping between
two types:</p>
<div class="highlight"><pre><span/><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">IdType</span><span class="p">.</span><span class="n">Foo</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Foo string"</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="w"> </span><span class="nf">if</span><span class="w"> </span><span class="p">(</span><span class="n">a</span><span class="w"> </span><span class="o">==</span><span class="w"> </span><span class="n">IdType</span><span class="p">.</span><span class="n">Bar</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Bar string"</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">...</span>
</pre></div>

<p>A pattern like this (which can also take the form of a big switch/case
statement) can usually be replaced with indexing into an array or
looking up the corresponding value in a hash map:</p>
<div class="highlight"><pre><span/><span class="n">Dictionary</span><span class="o">&lt;</span><span class="n">IdType</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="o">&gt;</span><span class="w"> </span><span class="n">IdTypeToStringMap</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">Dictionary</span><span class="o">&lt;</span><span class="n">IdType</span><span class="p">,</span><span class="w"> </span><span class="kt">string</span><span class="o">&gt;</span><span class="p">()</span>
<span class="p">{</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">IdType</span><span class="p">.</span><span class="n">Foo</span><span class="p">,</span><span class="w"> </span><span class="s">"Foo"</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="n">IdType</span><span class="p">.</span><span class="n">Bar</span><span class="p">,</span><span class="w"> </span><span class="s">"Bar"</span><span class="w"> </span><span class="p">},</span>
<span class="w">    </span><span class="p">...</span>
<span class="p">};</span>
<span class="p">...</span>
<span class="n">b</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">IdTypeToStringMap</span><span class="p">[</span><span class="n">a</span><span class="p">];</span>
</pre></div>

<p>This is, again, easier to maintain, since it is declarative - the
mapping is given as data (<code>IdTypeToStringMap</code>), not as code (long series
of if/else).</p>

<h3>Avoid loops</h3>

<p>This goes back to the C++ Seasoning talk, namely the <em>No Raw Loops</em>
guideline. Here's a C# example: given a list of numbers, we want to get
the square of all the odd numbers in the list.</p>
<div class="highlight"><pre><span/><span class="kt">var</span><span class="w"> </span><span class="n">numbers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">List</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="mi">6</span><span class="p">,</span><span class="w"> </span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">7</span><span class="p">,</span><span class="w"> </span><span class="mi">3</span><span class="p">,</span><span class="w"> </span><span class="mi">4</span><span class="p">,</span><span class="w"> </span><span class="mi">9</span><span class="p">,</span><span class="w"> </span><span class="mi">5</span><span class="p">,</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="p">};</span>

<span class="c1">// Get the squares of all odd numbers</span>
</pre></div>

<p>One way to do this is to maintain a list of numbers, iterate over the
list, check if numbers are odd, and if so, square them and add them to
the list:</p>
<div class="highlight"><pre><span/><span class="c1">// Get the squares of all odd numbers</span>
<span class="n">IEnumerable</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">SquareOdds</span><span class="p">(</span><span class="n">IEnumerable</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="kt">var</span><span class="w"> </span><span class="n">squares</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">List</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">();</span>

<span class="w">    </span><span class="k">foreach</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">number</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="n">squares</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">number</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">number</span><span class="p">);</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>

<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">squares</span><span class="p">;</span>
<span class="p">}</span>

<span class="kt">var</span><span class="w"> </span><span class="n">squares</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SquareOdds</span><span class="p">(</span><span class="n">numbers</span><span class="p">);</span>
</pre></div>

<p>A neater way to do this is to use a generator instead of manually
maintaining the list of squares:</p>
<div class="highlight"><pre><span/><span class="c1">// Get the squares of all odd numbers</span>
<span class="n">IEnumerable</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">SquareOdds</span><span class="p">(</span><span class="n">IEnumerable</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="p">{</span>
<span class="w">    </span><span class="k">foreach</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">numbers</span><span class="p">)</span>
<span class="w">    </span><span class="p">{</span>
<span class="w">        </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">number</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">)</span>
<span class="w">        </span><span class="p">{</span>
<span class="w">            </span><span class="k">yield</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">number</span><span class="p">;</span>
<span class="w">        </span><span class="p">}</span>
<span class="w">    </span><span class="p">}</span>
<span class="p">}</span>

<span class="kt">var</span><span class="w"> </span><span class="n">squares</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SquareOdds</span><span class="p">(</span><span class="n">numbers</span><span class="p">);</span>
</pre></div>

<p>That being said, what I would actually recommend is using Linq:</p>
<div class="highlight"><pre><span/><span class="c1">// Get the squares of all odd numbers</span>
<span class="kt">var</span><span class="w"> </span><span class="n">squares</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">numbers</span><span class="p">.</span>
<span class="w">                </span><span class="n">Where</span><span class="p">(</span><span class="n">number</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="o">%</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="o">!=</span><span class="w"> </span><span class="mi">0</span><span class="p">).</span>
<span class="w">                </span><span class="n">Select</span><span class="p">(</span><span class="n">number</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">number</span><span class="w"> </span><span class="o">*</span><span class="w"> </span><span class="n">number</span><span class="p">);</span>
</pre></div>

<p>Fewer lines of code and no branching whatsoever<sup id="fnref1"><a href="#fn1" rel="footnote">1</a></sup>. <code>Where</code> and
<code>Select</code> are generic algorithms, and their arguments are the predicates
we use. This makes the intent of the code clear at a glance - we are
filtering the collection with a predicate (<code>number =&gt; number % 2 != 0</code>)
and applying a transformation to it with another predicate
(<code>number =&gt; number * number</code>). Also, the filtering and transformation
are library functions, so we can be fairly certain they work well, and
only need to worry about maintaining our predicates.</p>

<p>It might not look like a big deal in this simple made-up example, but as
code evolves, it becomes harder and harder to follow the iteration
logic, as the code gets littered with <code>break</code>, <code>continue</code>, and <code>return</code>
statements (see the Chrome example quoted in the Write Less Code
section).</p>

<p>Key takeaways:</p>

<ul>
<li>Try to keep functions linear (or as linear as possible)</li>
<li>Default to throwing instead of propagating errors up the call stack</li>
<li>Consider creating a null object when code is littered with null
checks</li>
<li>Separate algorithm logic from predicates to make the intent of the
code clear (in other words, no raw loops).</li>
</ul>

<h2>Notes on performance</h2>

<p>The most interesting question I was asked is what are the performance
implications of using an STL algorithm or Linq.</p>

<p>The default answer is, of course, you have to measure for your
particular case! Blanket statements cannot be made about performance, as
there are many factors involved: compiler, runtime, standard library,
OS, architecture, whether code is on a hot path or not, and so on and so
forth.</p>

<p>Still, my recommendation is to use the library algorithms and, only if
they become the bottleneck (which in most cases shouldn't happen), look
into replacing them with handcrafted code. Another thing to keep in mind
is that standard library authors know what they're doing, so it's very
likely that library code is already pretty well optimized. I ran a
simple wall clock benchmark for 1M iterations for some of the examples I
used throughout the presentation (both the handcrafted and the library
versions), and in all cases the code leveraging library functions ran
slightly faster.</p>

<div class="footnotes">
<hr/>
<ol>

<li id="fn1">
<p>Cyclomatic complexity of this is actually higher when computed by
looking at basic blocks (eg. from Visual Studio's <code>Analyze</code> menu),
since the compiler will automatically add a finally block to dispose
of the Linq-returned IEnumerables in case of exception. That being
said, I prefer compiler-generated complexity to developer-generated
complexity. <a href="#fnref1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
]]></description>
      <pubDate>Mon, 04 Jan 2016 00:00:00 -0800</pubDate>
    </item>

  </channel>
</rss>
