<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://chiroptical.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://chiroptical.github.io/" rel="alternate" type="text/html" /><updated>2026-02-15T19:40:22+00:00</updated><id>https://chiroptical.github.io/feed.xml</id><title type="html">Chiroptical’s Blog</title><subtitle>A random blog about random stuff</subtitle><entry><title type="html">Why I re-wrote my Slack bot in Gleam</title><link href="https://chiroptical.github.io/posts/2025-02-13-re-write-slack-bot-in-gleam.html" rel="alternate" type="text/html" title="Why I re-wrote my Slack bot in Gleam" /><published>2025-02-13T00:00:00+00:00</published><updated>2025-02-13T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/re-write-slack-bot-in-gleam</id><content type="html" xml:base="https://chiroptical.github.io/posts/2025-02-13-re-write-slack-bot-in-gleam.html"><![CDATA[<h2 id="introduction">Introduction</h2>

<p>I started working on <a href="https://musicmonday.app">Music Monday</a> awhile back. It is currently
only a Slack bot which, when installed into a channel, selects a user at
random to suggest a musical album to share. This blog post isn’t about the
functionality, but the language change I made during implementation. Feel free
to check it out though, I need beta testers.</p>

<p>The bot was originally implemented in Erlang. I <strong>really</strong> like Erlang. The
language is quirky and simple. The BEAM is a gorgeous piece of technology to
build applications on. However, I’m a static types enjoyer. I write Haskell
professionally and I really really like having sum and product types.
To summarize, I want strong static types <strong>and</strong> I want <a href="https://www.erlang.org/doc/system/design_principles.html">Erlang/OTP</a>.</p>

<p>Enter <a href="https://gleam.run">Gleam</a>. I want to go over some specific examples where I feel
Gleam made my developer experience better.</p>

<h2 id="records">Records</h2>

<p>In Erlang, you can share records via header files, <code class="language-plaintext highlighter-rouge">.hrl</code>, e.g.,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">-</span><span class="ni">record</span><span class="p">(</span><span class="nl">slack_channel</span><span class="p">,</span> <span class="p">{</span><span class="n">id</span><span class="p">,</span> <span class="n">music_monday_id</span><span class="p">,</span> <span class="n">channel_id</span><span class="p">}).</span>
</code></pre></div></div>

<p>I used this record to denote a return type from a database query in <code class="language-plaintext highlighter-rouge">pgo</code>.
You can pattern match or access elements, e.g.,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">-</span><span class="ni">include_lib</span><span class="p">(</span><span class="s">"{filename}.hrl"</span><span class="p">).</span>

<span class="nl">#slack_channel</span><span class="p">{</span><span class="n">id</span> <span class="o">=</span> <span class="nv">Id</span><span class="p">}</span> <span class="o">=</span> <span class="nf">function_that_returns_slack_channel</span><span class="p">(),</span>
<span class="nv">SlackChannel</span> <span class="o">=</span> <span class="nf">function_that_returns_slack_channel</span><span class="p">(),</span>
<span class="nv">Id</span> <span class="o">=</span> <span class="nv">SlackChannel</span><span class="nl">#slack_channel.id</span><span class="p">,</span>
</code></pre></div></div>

<p>I don’t think this pattern is great <em>across</em> modules. You can give the fields
types and they can be checked with dialyzer/eqwalizer. That just doesn’t provide
<strong>me</strong> enough, I’m not a smart man. A compiler with expressive types, that
are checked, and easily shareable across modules saves me a lot of stress and
brainpower.</p>

<p>In Gleam, this record is defined,</p>

<pre><code class="language-gleam">import youid/uuid

pub type SlackChannel {
  SlackChannel(id: uuid.Uuid, music_monday_id: uuid.Uuid, channel_id: String)
}
</code></pre>

<p>I can import this type from anywhere via <code class="language-plaintext highlighter-rouge">import path/to/module.{type
SlackChannel}</code>. I can use it qualified via <code class="language-plaintext highlighter-rouge">import path/to/module</code> with
<code class="language-plaintext highlighter-rouge">module.SlackChannel</code>. It is easy to pass this type around and it works for both
Erlang and Javascript targets.</p>

<h2 id="database-queries">Database Queries</h2>

<p>With <code class="language-plaintext highlighter-rouge">pgo</code>, here is how I complete a unique insert into <code class="language-plaintext highlighter-rouge">slack_channel</code></p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">create_unique</span><span class="p">(</span><span class="nv">ChannelId</span><span class="p">)</span> <span class="o">-&gt;</span>
    <span class="err">#</span><span class="p">{</span><span class="n">command</span> <span class="p">:</span><span class="o">=</span> <span class="n">insert</span><span class="p">,</span> <span class="n">rows</span> <span class="p">:</span><span class="o">=</span> <span class="nv">Rows</span><span class="p">}</span> <span class="o">=</span> <span class="nn">pgo</span><span class="p">:</span><span class="nf">transaction</span><span class="p">(</span><span class="k">fun</span><span class="p">()</span> <span class="o">-&gt;</span>
        <span class="nn">pgo</span><span class="p">:</span><span class="k">query</span><span class="p">(</span>
            <span class="o">&lt;&lt;</span>
                <span class="s">"insert into slack_channel (channel_id)"</span>
                <span class="s">" values ($1)"</span>
                <span class="s">" on conflict (channel_id) do update"</span>
                <span class="s">" set channel_id = excluded.channel_id"</span>
                <span class="s">" returning id"</span>
            <span class="o">&gt;&gt;</span><span class="p">,</span>
            <span class="p">[</span><span class="nv">ChannelId</span><span class="p">]</span>
        <span class="p">)</span>
    <span class="k">end</span><span class="p">),</span>
    <span class="k">case</span> <span class="nv">Rows</span> <span class="k">of</span>
        <span class="p">[{</span><span class="nv">Id</span><span class="p">}]</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">Id</span><span class="p">};</span>
        <span class="p">_</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="n">error</span><span class="p">,</span> <span class="n">impossible</span><span class="p">}</span>
    <span class="k">end</span><span class="p">.</span>
</code></pre></div></div>

<p>Is <code class="language-plaintext highlighter-rouge">ChannelId</code> a UUID or String? Is <code class="language-plaintext highlighter-rouge">Id</code> a UUID or String? Is this query even
sound? In my Erlang application, I explicitly tested <strong>every</strong> query because
of the number of mistakes I made. I could add <code class="language-plaintext highlighter-rouge">-spec</code> annotations to this to
inform the reader but it doesn’t mean they are correct! Additionally, PostgreSQL
already knows this information! Why not just let PG figure out the types and
write the <code class="language-plaintext highlighter-rouge">{ok, Id}</code> and <code class="language-plaintext highlighter-rouge">{error, impossible}</code> logic ourselves. In Gleam, we
can use <a href="https://github.com/giacomocavalieri/squirrel">squirrel</a> for this. You add your query to a SQL file in the
module tree and squirrel will autogenerate the requisite Gleam code for you! For
the above query (with a slight modification) it will generate,</p>

<pre><code class="language-gleam">pub type CreateUniqueRow {
  CreateUniqueRow(id: Uuid)
}

pub fn create_unique(
  db: pog.Connection,
  arg_1: Uuid,
  arg_2: String,
) -&gt; Result(pog.Returned(CreateUniqueRow), pog.QueryError) {
  // ... generated code here
}
</code></pre>

<p>In my production application I needed an additional <code class="language-plaintext highlighter-rouge">Uuid</code> to create a
<code class="language-plaintext highlighter-rouge">slack_channel</code> (the internal Slack team identifier). This was partially why
I rewrote the application which I’ll explain in the next section. Here, I need
a <code class="language-plaintext highlighter-rouge">Uuid</code> and <code class="language-plaintext highlighter-rouge">String</code> to call this function and I’ll get back, effectively,
<code class="language-plaintext highlighter-rouge">Result(List(CreateUniqueRow), pog.QueryError)</code>. The <code class="language-plaintext highlighter-rouge">pog.Returned</code> type
also has a <code class="language-plaintext highlighter-rouge">count</code> field. You need to understand what <code class="language-plaintext highlighter-rouge">arg_1</code> and <code class="language-plaintext highlighter-rouge">arg_2</code> are
supposed to be, but the shape is generated automatically. You can, and probably
should, create a usable API around this function. For example, the logic above
expects only a single entry to come back from the query. Squirrel also provides
helpful error messages when your queries are broken.</p>

<h2 id="refactoring">Refactoring</h2>

<p>The initial Slack developer experience is okay if you are installing into a
single Slack team, but Music Monday is intended to be installed in <strong>many</strong>
Slacks. This requires OAuth credentials. I’ve not built applications like this
before so I made an assumption my bot is basically the same entity across Slack
but that isn’t true. Each team has its own credentials and even its own bot id.</p>

<p>When I built the Erlang application I was too tightly coupled with my
development Slack team. I needed to do a huge refactor to support Slack team ids
and OAuth credentials. In Erlang, there is no requirement to add dialyzer specs
so… I didn’t. I was in a hell hole of refactoring with the tests I had (which
actually was non-zero but far from full coverage) and debugging everything else
at runtime. It was pain.</p>

<p>After a few hours of this, I had enough. You can say, “skill issue” or “bad
tests and use of specs” and… you are right. To me, this is why strong static
types are <em>the way</em>. I am forced to do this <strong>and</strong> the compiler will help me.</p>

<p>Using the example above, I added the <code class="language-plaintext highlighter-rouge">slack_team</code> table and modified the
<code class="language-plaintext highlighter-rouge">slack_channel</code> table via migrations, re-ran <code class="language-plaintext highlighter-rouge">gleam run -m squirrel</code>, and ran
<code class="language-plaintext highlighter-rouge">gleam build</code>. Now, <strong>all</strong> the places I need to change are revealed to me. No
magic, no remembering. I just need to line up the new types.</p>

<p>This is true of internal blocks of code as well. In Erlang, when I pull out a
chunk of code, I have to figure out what the spec is supposed to be. In Gleam,
it was known before and it is known now. There is even a code action to do it.</p>

<h2 id="programming-the-happy-path">Programming the Happy Path</h2>

<p>Let’s start with an example using <code class="language-plaintext highlighter-rouge">maybe</code> from Erlang,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">maybe</span>
        <span class="p">{</span><span class="err">~</span><span class="s">"text"</span><span class="p">,</span> <span class="nv">Arguments</span><span class="p">}</span> <span class="o">?=</span> <span class="nn">proplists</span><span class="p">:</span><span class="nf">lookup</span><span class="p">(</span><span class="err">~</span><span class="s">"text"</span><span class="p">,</span> <span class="nv">Proplist</span><span class="p">),</span>
        <span class="p">{</span><span class="err">~</span><span class="s">"channel_id"</span><span class="p">,</span> <span class="nv">ChannelId</span><span class="p">}</span> <span class="o">?=</span> <span class="nn">proplists</span><span class="p">:</span><span class="nf">lookup</span><span class="p">(</span><span class="err">~</span><span class="s">"channel_id"</span><span class="p">,</span> <span class="nv">Proplist</span><span class="p">),</span>
        <span class="p">{</span><span class="err">~</span><span class="s">"user_id"</span><span class="p">,</span> <span class="nv">UserId</span><span class="p">}</span> <span class="o">?=</span> <span class="nn">proplists</span><span class="p">:</span><span class="nf">lookup</span><span class="p">(</span><span class="err">~</span><span class="s">"user_id"</span><span class="p">,</span> <span class="nv">Proplist</span><span class="p">),</span>
        <span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="p">{</span><span class="n">slack_command</span><span class="p">,</span> <span class="nv">Arguments</span><span class="p">,</span> <span class="nv">UserId</span><span class="p">,</span> <span class="nv">ChannelId</span><span class="p">}}</span>
    <span class="n">else</span>
        <span class="n">none</span> <span class="o">-&gt;</span> <span class="p">{</span><span class="n">error</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"Unable to construct slack_command from_proplist"</span><span class="o">&gt;&gt;</span><span class="p">}</span>
    <span class="k">end</span><span class="p">.</span>
</code></pre></div></div>

<p>Here, I’m trying to lookup some keys in a “proplist” (a list of key-value
tuples). They all need to be present to succeed. If <code class="language-plaintext highlighter-rouge">proplists:lookup</code>
succeeds it returns <code class="language-plaintext highlighter-rouge">{Key, Value}</code> if it fails it returns <code class="language-plaintext highlighter-rouge">none</code>. This
API is actually quite friendly for <code class="language-plaintext highlighter-rouge">maybe</code> expressions, others aren’t.</p>

<p>First, the <code class="language-plaintext highlighter-rouge">?=</code> syntax is saying, if the left side of the expression is
a successful pattern match continue otherwise go to the <code class="language-plaintext highlighter-rouge">else</code> block and
start pattern matching. Let’s imagine that an update to the proplists API
caused <code class="language-plaintext highlighter-rouge">proplists:lookup</code> to <code class="language-plaintext highlighter-rouge">error</code> instead of <code class="language-plaintext highlighter-rouge">none</code> <strong>or</strong> <code class="language-plaintext highlighter-rouge">{error,
not_a_proplist}</code> if you don’t provide a proplist. In either of those update
scenarios, my pattern match would fail. Tools like dialyzer won’t catch this,
but I believe other projects are working on full compilers for Erlang, e.g.
https://github.com/etylizer/etylizer.</p>

<p>In Gleam, I just don’t have this problem because I am using a compiler with
exhaustiveness checking. I have a few options for coding this in Gleam, e.g.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>// Note: I could use type to distinguish between parse_query failure and lookup failure
// Nil is used for simplicity
case uri.parse_query(a_string) { // https://hexdocs.pm/gleam_stdlib/0.69.0/gleam/uri.html#parse_query
  Error(Nil) -&gt; Error(Nil)
  Ok(a_proplist) -&gt; {
    case list.key_find(a_proplist, "text"), list.key_find(a_proplist, "channel_id"), list.key_find(a_proplist, "user_id") {
      Ok(args), Ok(channel_id), Ok(user_id) -&gt; Ok(#(args, channel_id, user_id))
      _, _, _ -&gt; Error(Nil)
    }
  }  
}
</code></pre></div></div>

<p>I personally find the <code class="language-plaintext highlighter-rouge">Result</code> <code class="language-plaintext highlighter-rouge">use</code> style more readable, but I’ll elide that
for simplicity. The key is that my pattern match <strong>has</strong> to be exhaustive,
I couldn’t write,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    Ok(args), Ok(channel_id), Ok(user_id) -&gt; Ok(#(args, channel_id, user_id))
    Error(Nil), Error(Nil), Error(Nil) -&gt; Error(Nil)
</code></pre></div></div>

<p>the compiler will <strong>tell me</strong> I goofed up. I like that. Additionally, if I want
to use some other error type the compiler will help me refactor e.g. if I wanted
to use a validation monad (I had to sneak the ‘m’ word in here). Additionally,
if the shape is updated I’ll get a compiler error. Note: be careful using blanket
pattern matches, e.g. <code class="language-plaintext highlighter-rouge">_, _, _ -&gt;</code> above, because you could miss API updates!</p>

<h2 id="adding-a-front-end">Adding a Front-end</h2>

<p>There is only a small footprint of front-end code for Music Monday today.
Essentially an install button, some frequently asked questions, and a page to
describe how to use the bot after it is installed. However, if I want to do
something more interesting there aren’t many friendly and maintained Erlang
frameworks to build with. I think <a href="https://www.novaframework.org/">Nova</a> looks interesting though.</p>

<p>The only times I have ever really enjoyed writing front-end are with Elm.
Typescript is a tedious language and doesn’t <em>really</em> have a language server
outside of VSCode. Editing in Helix with the LSP is basically useless. React’s
hooks are getting easier for me, but the number of times I’ve had to think
incredibly deeply about the runtime is brutal. I want a simpler language with a
better editor experience. Enter <a href="https://github.com/lustre-labs/lustre">Lustre</a>.</p>

<p>It was very easy for me to get a server-side rendered application
together. The types were easy to figure out, examples exist, and a
decent amount of documentation is available. I can use the editor
I prefer with actually useful LSP functionality. I already have a
Tailwind Plus subscription so it was easy to drop the HTML into <a href="https://lpil.github.io/html-lustre-converter/">this
converter</a> (thanks Louis!) and
get the Lustre representation.</p>

<h2 id="erlangotp">Erlang/OTP</h2>

<p>I’m not going to be able to convince you that Erlang/OTP rocks. There
are better posts that cover that in <strong>way</strong> more detail. You are just
going to have to believe me for now. With a combination of <a href="https://hexdocs.pm/gleam_otp">factory
supervisors</a> (in Erlang, simple-one-for-one
supervisors) and <a href="https://hexdocs.pm/crew/index.html">crew</a> I was able to
introduce services and back-pressure into my system with little effort. Slack
has team based API limits and I’d like to be able to build with this in mind.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Gleam gave me all the tools I needed to be successful. The language is simple
and can be picked up quickly. The community is stellar and super helpful. You
can build full-stack applications with one language. If you are looking for
a strong statically typed language, check out Gleam. You’ll also, eventually,
learn about Erlang/OTP which has really nice patterns to help build robust
software.</p>

<p>Feel free to send me a direct message on <a href="https://bsky.app/profile/chiroptical.dev">BlueSky</a> if you have any
questions, corrections, or want to tell me I’m wrong. I’m always happy to learn
new things.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Introduction]]></summary></entry><entry><title type="html">Leex and yecc by example: part 2</title><link href="https://chiroptical.github.io/posts/2024-12-04-leex-yeex-by-example-part-2.html" rel="alternate" type="text/html" title="Leex and yecc by example: part 2" /><published>2024-12-04T00:00:00+00:00</published><updated>2024-12-04T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/leex-yeex-by-example-part-2</id><content type="html" xml:base="https://chiroptical.github.io/posts/2024-12-04-leex-yeex-by-example-part-2.html"><![CDATA[<h2 id="welcome-to-part-2">Welcome to Part 2!</h2>

<p><a href="/posts/2024-12-03-leex-yeex-by-example-part-1.html">In part 1</a>,
we went over our first example of using leex and yecc. In
this blog post, I’ll lex/parse <a href="https://adventofcode.com/2024/day/4">Advent of code 2024 day 4</a> and simplify
day 3 using an observation from day 4. I am still learning too.</p>

<h2 id="day-4-ceres-search">Day 4: Ceres Search</h2>

<p>In this problem, we are given a matrix of <code class="language-plaintext highlighter-rouge">X</code>, <code class="language-plaintext highlighter-rouge">M</code>, <code class="language-plaintext highlighter-rouge">A</code>, and <code class="language-plaintext highlighter-rouge">S</code>s we are
basically doing a word search puzzle for <code class="language-plaintext highlighter-rouge">XMAS</code> horizontally, vertically, or
diagonally. It can also appear forward or backward. An abbreviated input,</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>MMMSXX
MSAMXM
AMXSXM
MSAMAS
</code></pre></div></div>

<p>When I see problems like this I usually reach for <code class="language-plaintext highlighter-rouge">maps</code> because I need to
search in the vicinity of every element. Essentially, for the first <code class="language-plaintext highlighter-rouge">M</code> in that
input I want <code class="language-plaintext highlighter-rouge">{{1, 1}, m}</code>. Conveniently, that is the exact
format I need to use <a href="https://www.erlang.org/doc/apps/stdlib/maps.html#from_list/1">maps:from_list/2</a>.</p>

<p>First, I’ll drop the leex file and then discuss the various sections,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Definitions.

XMAS    = [XMAS]
NEWLINE = \n

Rules.

{XMAS}    : {token, {xmas, TokenLoc, to_atom(TokenChars)}}.
{NEWLINE} : skip_token.

Erlang code.

to_atom("X") -&gt;
	x;
to_atom("M") -&gt;
	m;
to_atom("A") -&gt;
	a;
to_atom("S") -&gt;
	s.
</code></pre></div></div>

<p>In the definitions section we only have <code class="language-plaintext highlighter-rouge">XMAS</code> which is any one of our
characters. Note, you would use <code class="language-plaintext highlighter-rouge">[A-Z]</code> if you wanted any capital letter
but we only care about the specific letters. We also have newlines
which you’ve seen before.</p>

<p>The rules show two nice things we have at our disposal. <code class="language-plaintext highlighter-rouge">TokenLoc</code> will tell us
exacly the row and column our token was found in the format <code class="language-plaintext highlighter-rouge">{Row, Column}</code>.
Additionally, <code class="language-plaintext highlighter-rouge">skip_token</code> is simply dropping the token entirely. We don’t
really care about the newlines because we get the position from <code class="language-plaintext highlighter-rouge">TokenLoc</code>.
We can also run <code class="language-plaintext highlighter-rouge">to_atom/1</code> on our token to convert it into an atom. Amazing!
The output of our lexer looks like,</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[{xmas,{1,1},m},
 {xmas,{1,2},m},
 {xmas,{1,3},m},
 ...]
</code></pre></div></div>

<p>Much simpler than day 3. Next our yecc file which I’ll discuss below,</p>

<div class="language-text highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Nonterminals chars.

Terminals xmas.

Rootsymbol chars.

chars -&gt; xmas       : [reshape('$1')].
chars -&gt; xmas chars : [reshape('$1')|'$2'].

Erlang code.

reshape({xmas, {Row, Col}, Xmas}) -&gt;
	{{Row, Col}, Xmas}.
</code></pre></div></div>

<p>We only have one terminal this time <code class="language-plaintext highlighter-rouge">xmas</code>. Additionally, we only have
one non-terminal which I called <code class="language-plaintext highlighter-rouge">chars</code>. A <code class="language-plaintext highlighter-rouge">chars</code> can either be an <code class="language-plaintext highlighter-rouge">xmas</code>
(base case) or <code class="language-plaintext highlighter-rouge">xmas</code> followed by <code class="language-plaintext highlighter-rouge">chars</code> (recursive case). Finally, we just
<code class="language-plaintext highlighter-rouge">reshape/1</code> to get our desired shape for <code class="language-plaintext highlighter-rouge">maps:from_list/2</code> and we are done!</p>

<p>My solution is <a href="https://github.com/chiroptical/advent_of_code_2024/blob/main/src/solution_day_4_2024.erl">here</a>. I plan on doing some refactoring
but it is currently working.</p>

<h2 id="refactor-day-3">Refactor Day 3</h2>

<p>If you haven’t read <a href="/posts/2024-12-03-leex-yeex-by-example-part-1.html">part 1</a> the following
explanation isn’t going to make a lot of sense.</p>

<p>In the previous example, we completely ignored the newlines. In day 3, we also
don’t care about the newlines! The “memory” described in the problem is just
a contiguous string of characters. We can make some basic changes to our lexer
and parser to simplify our application code from dealing with a list of list
of inputs.</p>

<p>In the lexer, we can either change the newline rule to,</p>

<ol>
  <li><code class="language-plaintext highlighter-rouge">{NEWLINE} : {token, {skip, TokenLine}}.</code></li>
  <li><code class="language-plaintext highlighter-rouge">{NEWLINE} : skip_token.</code></li>
</ol>

<p>I chose “1.” because I don’t really care about a few extra <code class="language-plaintext highlighter-rouge">skip</code>
tokens. Ideally, I could change the else definition to <code class="language-plaintext highlighter-rouge">ELSE =
[^all_unimportant_characters]</code>. The <code class="language-plaintext highlighter-rouge">[^abc]</code> syntax means inverse i.e. all
characters but <code class="language-plaintext highlighter-rouge">a</code>, <code class="language-plaintext highlighter-rouge">b</code>, <code class="language-plaintext highlighter-rouge">c</code>. The regex in leex is not powerful enough to
say “anything except a number, do, don’t, parentheses, or comma”.
I could just add a bunch of symbols to a list,
e.g. <code class="language-plaintext highlighter-rouge">[%^&amp;*$#\s\n]</code> but I don’t like brute forcing the possible symbols in the
input. I only point this out because it is a limitation you may want to know about.
Documentation is <a href="https://www.erlang.org/doc/apps/parsetools/leex.html#module-regular-expressions">here</a> for reference.</p>

<p>In the parser, we remove the non-terminal <code class="language-plaintext highlighter-rouge">computer</code>, the terminal <code class="language-plaintext highlighter-rouge">newline</code>,
and change the <code class="language-plaintext highlighter-rouge">Rootsymbol</code> to <code class="language-plaintext highlighter-rouge">memory</code>. That is literally it. You’ll
end up with an input to your application like,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[{operands,{2,4}},
 {operands,{5,5}},
 {operands,{11,8}},
 {operands,{8,5}},
 ...]
</code></pre></div></div>

<p>With this simplification, I was able to remove about 20 lines from my
application code that just folded over that outer list. Links to the new files
for reference,</p>

<ul>
  <li><a href="https://github.com/chiroptical/advent_of_code_2024/blob/main/src/lexer_day_3_2024.xrl">lexer</a></li>
  <li><a href="https://github.com/chiroptical/advent_of_code_2024/blob/main/src/parser_day_3_2024.yrl">parser</a></li>
  <li><a href="https://github.com/chiroptical/advent_of_code_2024/blob/main/src/solution_day_3_2024.erl">solution</a></li>
</ul>

<h2 id="conclusion">Conclusion</h2>

<p>I hope leex and yecc are already getting easier to use. More examples coming.
If you have any suggestions, questions, or corrections hit me up on <a href="https://bsky.app/profile/chiroptical.dev">bluesky</a>.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Welcome to Part 2!]]></summary></entry><entry><title type="html">Leex and yecc by example: part 1</title><link href="https://chiroptical.github.io/posts/2024-12-03-leex-yeex-by-example-part-1.html" rel="alternate" type="text/html" title="Leex and yecc by example: part 1" /><published>2024-12-03T00:00:00+00:00</published><updated>2024-12-03T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/leex-yeex-by-example-part-1</id><content type="html" xml:base="https://chiroptical.github.io/posts/2024-12-03-leex-yeex-by-example-part-1.html"><![CDATA[<h1 id="background">Background</h1>

<p><a href="https://adventofcode.com">Advent of code</a> is here and every year I use a parser combinator library
to handle the inputs. Lately, I have been into Erlang but I couldn’t find a
parser combinator library that I liked. However, Erlang does have <a href="https://www.erlang.org/doc/apps/parsetools/leex.html">leex</a>
and <a href="https://www.erlang.org/doc/apps/parsetools/yecc.html">yecc</a>. Leex is a lexical analyzer generator and yecc is a LALR-1
parser generator. I have never used tools like these before and it seemed
like a great opportunity. However, the documentation and examples are a little
sparse for getting started. Therefore, I decided to start this series as a
medium to present examples of lexers and parsers in Erlang using leex and yecc!</p>

<p>I am not going to dive into the theory of these tools. I really just want to jam
something examples into your brain piece so you can play with them. If you
want to dive into theory later, be my guest.</p>

<h1 id="day-3-mull-it-over">Day 3: Mull It Over</h1>

<p>This is the first example which isn’t just numbers separated by spaces. It is
a great lexing and parsing example.  The <a href="https://adventofcode.com/2024/day/3">problem on advent of code</a>. The
basic idea is you have an input,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>xmul(2,4)%&amp;mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))
</code></pre></div></div>

<p>In the text, you’ll see some <code class="language-plaintext highlighter-rouge">mul(A,B)</code>. We want to find all of these in
the input, multiply the numbers <code class="language-plaintext highlighter-rouge">A</code> and <code class="language-plaintext highlighter-rouge">B</code> together, then sum all of the
multiplications. There are corrupted versions which you aren’t allowed
to count, e.g. <code class="language-plaintext highlighter-rouge">mul(A, B)</code>, <code class="language-plaintext highlighter-rouge">mul(A,B</code>, <code class="language-plaintext highlighter-rouge">?(A,B)</code>. I think most people
will use regex to solve this problem, i.e. <code class="language-plaintext highlighter-rouge">mul\([0-9]+,[0-9]+\)</code>.
How would we do this with leex and yecc?</p>

<h1 id="lexing">Lexing</h1>

<p>Lexing is a process of breaking a string into tokens. In our case, the
tokens would be <code class="language-plaintext highlighter-rouge">mul</code>, <code class="language-plaintext highlighter-rouge">(</code>, <code class="language-plaintext highlighter-rouge">,</code>, <code class="language-plaintext highlighter-rouge">)</code>, or a number. In part 2, we also need <code class="language-plaintext highlighter-rouge">do</code>,
<code class="language-plaintext highlighter-rouge">don't</code>. Finally, we also need to represent the rest of the input i.e. <code class="language-plaintext highlighter-rouge">space</code>,
<code class="language-plaintext highlighter-rouge">newline</code>, <code class="language-plaintext highlighter-rouge">skip</code>. The <code class="language-plaintext highlighter-rouge">skip</code> token is going to represent any token that isn’t
relevant to us. For example, the tokenized version of <code class="language-plaintext highlighter-rouge">xmul(2,4)%&amp;</code> is approximately <code class="language-plaintext highlighter-rouge">['skip',
'mul', '(', '2', ',', '4', ')', skip, skip]</code>. We’ll feed the tokenization to the
parser in the next step. First, let’s discuss how to describe the lexer using
leex.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Definitions.

INT         = [0-9]+
MULTIPLY    = mul
DO          = do\(\)
DONT        = don't\(\)
OPEN_PAREN  = \(
CLOSE_PAREN = \)
COMMA       = ,
SPACE       = \s+
NEWLINE     = \n
ELSE        = .
</code></pre></div></div>

<p>The first section of the leex file describes our tokens. It uses a relatively
simplistic regex language to describe the tokens. More documentation <a href="https://www.erlang.org/doc/apps/parsetools/leex.html#module-regular-expressions">here</a>.
<code class="language-plaintext highlighter-rouge">INT = [0-9]+</code> means an <code class="language-plaintext highlighter-rouge">INT</code> is described as one or more of any single number
between 0 and 9. <code class="language-plaintext highlighter-rouge">SPACE = \s+</code> means a <code class="language-plaintext highlighter-rouge">SPACE</code> is described as one or more space
characters. <code class="language-plaintext highlighter-rouge">ELSE = .</code> means <code class="language-plaintext highlighter-rouge">ELSE</code> is described as any character.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Rules.

{INT}                 : {token, {int, TokenLine, list_to_integer(TokenChars)}}.
{MULTIPLY}            : {token, {mul, TokenLine}}.
{DO}                  : {token, {do, TokenLine}}.
{DONT}                : {token, {dont, TokenLine}}.
{OPEN_PAREN}          : {token, {open_paren, TokenLine}}.
{CLOSE_PAREN}         : {token, {close_paren, TokenLine}}.
{COMMA}               : {token, {comma, TokenLine}}.
{SPACE}               : {token, {space, TokenLine}}.
{NEWLINE}             : {token, {newline, TokenLine}}.
{ELSE}                : {token, {skip, TokenLine}}.  
</code></pre></div></div>

<p>The rules are evaluated in order from top to bottom. All of these rules are
generating tokens, but you could also <code class="language-plaintext highlighter-rouge">: skip_token</code> or return an error <code class="language-plaintext highlighter-rouge">:
{error, "..."}</code>. In <code class="language-plaintext highlighter-rouge">{token, X}</code>, <code class="language-plaintext highlighter-rouge">X</code> must be a tuple and it can be any length
but must start with an atom. We’ll use that atom in the parser shortly. You can
also use Erlang code here! For example, we really want <code class="language-plaintext highlighter-rouge">2</code> and not <code class="language-plaintext highlighter-rouge">"2"</code> so we
use a builtin <code class="language-plaintext highlighter-rouge">list_to_integer/1</code> to convert. <code class="language-plaintext highlighter-rouge">TokenLine</code> is a leex variable
which is filled in with the line number from the input. There is also <code class="language-plaintext highlighter-rouge">TokenLoc</code>
which gives you <code class="language-plaintext highlighter-rouge">{Line, Column}</code>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Erlang code.
</code></pre></div></div>

<p>This is the final section. I don’t need any special Erlang code here, but we’ll
use this section in the parser.</p>

<p>If you are using <a href="https://rebar3.org">rebar3</a>, and you stick these sections into a single file like
<code class="language-plaintext highlighter-rouge">src/lexer.xrl</code> it will auto-generate a file <code class="language-plaintext highlighter-rouge">src/lexer.erl</code> which contains
<code class="language-plaintext highlighter-rouge">lexer:lex/1</code>. If you pass that a string, it will try to lex it. For the
following example (the test input),</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">lexer</span><span class="p">:</span><span class="nf">lex</span><span class="p">(</span><span class="s">"xmul(2,4)%&amp;mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"</span><span class="p">).</span>
</code></pre></div></div>

<p>you get (truncated for article length),</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[{skip,1},
 {mul,1},
 {open_paren,1},
 {int,1,2},
 {comma,1},
 {int,1,4},
 {close_paren,1},
 {skip,1},
 {skip,1},
 ...]
</code></pre></div></div>

<p>See how it is just a list of tokens! Let’s parse it!</p>

<h1 id="parser">Parser</h1>

<p>Parsing will take the list of tokens and interpret them into a data structure
convenient for our computation. In our case, we only care about the numbers
(<code class="language-plaintext highlighter-rouge">int</code>), <code class="language-plaintext highlighter-rouge">do</code> and <code class="language-plaintext highlighter-rouge">don't</code>. In part 1, we only need the numbers. For example,
given the above lexed output we want <code class="language-plaintext highlighter-rouge">[{operands, {2, 4}}]</code> to come out of
parser. <code class="language-plaintext highlighter-rouge">operands</code> is arbitrary, we could have used <code class="language-plaintext highlighter-rouge">spaceship</code>. Our program
decides what to do with the output of the parser.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Nonterminals instruction memory computer else.

Terminals mul int open_paren close_paren comma space newline skip do dont.

Rootsymbol computer.
</code></pre></div></div>

<p>The terminals are just the atoms from our lexer, hopefully you recognize them.
The non-terminals describe the pieces we want to pull out,</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">instruction</code>: <code class="language-plaintext highlighter-rouge">{operand, {X, Y}}</code>, <code class="language-plaintext highlighter-rouge">enable</code>, <code class="language-plaintext highlighter-rouge">disable</code></li>
  <li><code class="language-plaintext highlighter-rouge">memory</code>: a list of <code class="language-plaintext highlighter-rouge">instruction</code>s</li>
  <li><code class="language-plaintext highlighter-rouge">computer</code>: a list of <code class="language-plaintext highlighter-rouge">memory</code>s</li>
  <li><code class="language-plaintext highlighter-rouge">else</code>: everything we want to skip</li>
</ul>

<p>I chose to translate <code class="language-plaintext highlighter-rouge">do -&gt; enable</code>, <code class="language-plaintext highlighter-rouge">don't -&gt; disable</code> because it seemed
more obvious when writing the solution. The <code class="language-plaintext highlighter-rouge">Rootsymbol</code> determines the
starting point. In our case, we are parsing the <code class="language-plaintext highlighter-rouge">computer</code> as a list of list
of instructions. The next section of the yecc file is a bit large in this case
but I prefer to show code before the example. I like to put a blank line in
between each non-terminal for readability.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>instruction -&gt; mul open_paren int comma int close_paren : {ok, operands, {extract_integer('$3'), extract_integer('$5')}}.
instruction -&gt; mul open_paren int comma int             : incomplete.
instruction -&gt; mul open_paren int comma                 : incomplete.
instruction -&gt; mul open_paren int                       : incomplete.
instruction -&gt; mul open_paren                           : incomplete.
instruction -&gt; do                                       : {ok, enable}.
instruction -&gt; dont                                     : {ok, disable}.
instruction -&gt; else                                     : incomplete.

memory -&gt; instruction             : remove_incomplete('$1').
memory -&gt; instruction memory      : remove_incomplete_rec('$1', '$2').

computer -&gt; memory           : ['$1'].
computer -&gt; memory computer  : ['$1'|'$2'].

else -&gt; mul.
else -&gt; int.
else -&gt; open_paren.
else -&gt; close_paren.
else -&gt; comma.
else -&gt; space.
else -&gt; newline.
else -&gt; skip.
</code></pre></div></div>

<p>This section describes all the rules. A single rule is constructed with a
non-terminal <code class="language-plaintext highlighter-rouge">instruction -&gt;</code>, it’s
definition <code class="language-plaintext highlighter-rouge">mul open_paren int comma int close_paren</code>, and what we do with
it <code class="language-plaintext highlighter-rouge">: {ok, operands, {extract_integer('$3'), extract_integer('$5')}}.</code>. The
definition is literally the atoms from the tokenized output in that exact order.
If you have a <code class="language-plaintext highlighter-rouge">space</code> in between any of those the rule will fail. Each token is
identified using this odd syntax, i.e. <code class="language-plaintext highlighter-rouge">'$3'</code> is the first <code class="language-plaintext highlighter-rouge">int</code> token.
The return is just an Erlang value. We can use built-ins or add code in an <code class="language-plaintext highlighter-rouge">Erlang code.</code> section (which I use in this case).
After the matching rule, we have to describe all the <code class="language-plaintext highlighter-rouge">incomplete</code> sequences.
If you don’t do this, you get very weird errors. Those errors are trying to
explain to you that you <strong>must</strong> have these 6 tokens in order and I only found
e.g. <code class="language-plaintext highlighter-rouge">mul open_paren</code>, but I can’t find an <code class="language-plaintext highlighter-rouge">int</code> after it. Try commenting those out
and check the error message, it isn’t great. Finally, we have <code class="language-plaintext highlighter-rouge">do</code>, <code class="language-plaintext highlighter-rouge">dont</code>, and anything <code class="language-plaintext highlighter-rouge">else</code>.</p>

<p>The <code class="language-plaintext highlighter-rouge">else</code> non-terminals are just any singular token not matching our incomplete
<code class="language-plaintext highlighter-rouge">mul(1,2)</code> example. Note how I don’t include <code class="language-plaintext highlighter-rouge">do</code> and <code class="language-plaintext highlighter-rouge">dont</code> there, I always
want to parse those.</p>

<p>The <code class="language-plaintext highlighter-rouge">memory</code> non-terminal is recursive and so you need a base case.
Our base case is just an <code class="language-plaintext highlighter-rouge">instruction</code> and the recursive case is
an <code class="language-plaintext highlighter-rouge">instruction</code> followed by <code class="language-plaintext highlighter-rouge">memory</code>. You’ll see these recursive definitions
a lot with advent of code problems. The <code class="language-plaintext highlighter-rouge">computer</code> is very similar but replace
<code class="language-plaintext highlighter-rouge">instruction</code> with <code class="language-plaintext highlighter-rouge">memory</code>.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Erlang code.

extract_integer({_Token, _Line, Value}) -&gt; Value.

remove_incomplete({ok, operands, {A, B}}) -&gt;
	[{operands, {A, B}}];
remove_incomplete({ok, enable}) -&gt;
	[enable];
remove_incomplete({ok, disable}) -&gt;
	[disable];
remove_incomplete(incomplete) -&gt;
	[].

remove_incomplete_rec({ok, operands, {A, B}}, Rest) -&gt;
	[{operands, {A, B}} | Rest];
remove_incomplete_rec({ok, enable}, Rest) -&gt;
	[enable | Rest];
remove_incomplete_rec({ok, disable}, Rest) -&gt;
	[disable | Rest];
remove_incomplete_rec(incomplete, X) -&gt;
	X.
</code></pre></div></div>

<p>Finally, our Erlang code to process. We are just removing the <code class="language-plaintext highlighter-rouge">incomplete</code>s
from our final result and reshaping the operands, enable, and disable to avoid
dealing with the <code class="language-plaintext highlighter-rouge">ok</code>s in our application code.</p>

<p>If you are using <code class="language-plaintext highlighter-rouge">rebar3</code> you will get auto-generation here too. A file
<code class="language-plaintext highlighter-rouge">src/parser.yrl</code> will generate <code class="language-plaintext highlighter-rouge">src/parser.erl</code> which has <code class="language-plaintext highlighter-rouge">parse/1</code>.</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">Lex</span><span class="p">}</span> <span class="o">=</span> <span class="nn">lexer</span><span class="p">:</span><span class="nf">lex</span><span class="p">(</span><span class="s">"xmul(2,4)%&amp;mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"</span><span class="p">),</span>
<span class="nn">parser</span><span class="p">:</span><span class="nf">parse</span><span class="p">(</span><span class="nv">Lex</span><span class="p">).</span>
</code></pre></div></div>

<p>will output</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[[{operands,{2,4}},
  {operands,{5,5}},
  {operands,{11,8}},
  {operands,{8,5}}]]
</code></pre></div></div>

<p>Amazing! Solving the problem is trivial from here!</p>

<h1 id="conclusion">Conclusion</h1>

<p>This was just our first example using leex and yecc. We are going to go over a
lot more examples in the series. For example, <a href="https://adventofcode.com/2023/day/1">2023 day 1</a> makes use
of a neat leex feature. If you have any suggestions, questions, or corrections
hit me up on <a href="https://bsky.app/profile/chiroptical.dev">bluesky</a>.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Background]]></summary></entry><entry><title type="html">Setting up Erlang CI with PostgreSQL</title><link href="https://chiroptical.github.io/posts/2024-08-07-erlang-postgresql-setup.html" rel="alternate" type="text/html" title="Setting up Erlang CI with PostgreSQL" /><published>2024-08-07T00:00:00+00:00</published><updated>2024-08-07T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/erlang-postgresql-setup</id><content type="html" xml:base="https://chiroptical.github.io/posts/2024-08-07-erlang-postgresql-setup.html"><![CDATA[<h1 id="overview">Overview</h1>

<p>In this blog post, I’ll quickly discuss how I got Erlang and PostgreSQL set up in GitHub CI.
Additionally, I discuss how I set up single use databases for my test infrastructure.</p>

<h1 id="assumptions">Assumptions</h1>

<p>You at least have some familiarity with GitHub Actions and Erlang.</p>

<h2 id="erlang-in-github-actions">Erlang in GitHub Actions</h2>

<p>This is actually very easy thanks to the Erlang Foundation’s <a href="https://github.com/erlef/setup-beam">setup-beam</a> action.
Here is the top of my <code class="language-plaintext highlighter-rouge">ci.yaml</code> file,</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">on</span><span class="pi">:</span> <span class="s">push</span>

<span class="na">jobs</span><span class="pi">:</span>
  <span class="na">test</span><span class="pi">:</span>
    <span class="na">runs-on</span><span class="pi">:</span> <span class="s">ubuntu-22.04</span>
    <span class="na">name</span><span class="pi">:</span> <span class="s">Erlang/OTP ${{matrix.otp}} / rebar3 ${{matrix.rebar3}}</span>
    <span class="na">strategy</span><span class="pi">:</span>
      <span class="na">matrix</span><span class="pi">:</span>
        <span class="na">otp</span><span class="pi">:</span> <span class="pi">[</span><span class="s1">'</span><span class="s">26.2.2'</span><span class="pi">]</span>
        <span class="na">rebar3</span><span class="pi">:</span> <span class="pi">[</span><span class="s1">'</span><span class="s">3.22.1'</span><span class="pi">]</span>
    <span class="na">steps</span><span class="pi">:</span>
      <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">actions/checkout@v4</span>
      <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">erlef/setup-beam@v1</span>
        <span class="na">with</span><span class="pi">:</span>
          <span class="na">otp-version</span><span class="pi">:</span> <span class="s">${{matrix.otp}}</span>
          <span class="na">rebar3-version</span><span class="pi">:</span> <span class="s">${{matrix.rebar3}}</span>
</code></pre></div></div>

<p>I am building and testing an application here, so having an intensive matrix isn’t particularly helpful.
Next, the actual checks and tests I want to run,</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      <span class="c1"># The Erlang files should be formatted</span>
      <span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">rebar3 fmt --check</span>
      <span class="c1"># Run eunit</span>
      <span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">rebar3 eunit</span>
      <span class="c1"># Run common test</span>
      <span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">rebar3 ct</span>
</code></pre></div></div>

<p>This is essentially all you need to do both <a href="https://www.erlang.org/doc/apps/eunit/chapter.html">eunit</a> and <a href="https://www.erlang.org/doc/apps/common_test/basics_chapter.html">commontest</a> tests.</p>

<h2 id="single-use-databases">Single use databases</h2>

<p>With common test, I can have build-up and tear-down callbacks for every suite
and every test. Using these callbacks, I can create, migrate, and destroy a
single use database for each test that needs them. Let’s look at an example Erlang
common test suite. Set up our Erlang module, include eunit macros, and export
all the functions in the module so common test can run them,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">-</span><span class="ni">module</span><span class="p">(</span><span class="n">temporary_database_SUITE</span><span class="p">).</span>
<span class="p">-</span><span class="ni">include_lib</span><span class="p">(</span><span class="s">"eunit/include/eunit.hrl"</span><span class="p">).</span>
<span class="p">-</span><span class="ni">compile</span><span class="p">(</span><span class="n">export_all</span><span class="p">).</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">all/0</code> callback tells common test which tests to run. We’ll look at the actual
test last.</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">all</span><span class="p">()</span> <span class="o">-&gt;</span>
    <span class="p">[</span><span class="n">the_current_database_is_the_temporary_one_and_contains_public_tables</span><span class="p">].</span>
</code></pre></div></div>

<p>These callbacks initialize state for this test suite. In this case, I start
pgo and ensure all of the environment variables are set up for pgo. This
<code class="language-plaintext highlighter-rouge">Config</code> variable can be used to store state for your tests or explain to the
<code class="language-plaintext highlighter-rouge">end_per_suite/1</code> function what to destroy. This isn’t really a tutorial on
common test.</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">init_per_suite</span><span class="p">(</span><span class="nv">Config</span><span class="p">)</span> <span class="o">-&gt;</span>
    <span class="nn">application</span><span class="p">:</span><span class="nf">ensure_all_started</span><span class="p">(</span><span class="n">pgo</span><span class="p">),</span>
    <span class="nn">environment</span><span class="p">:</span><span class="nf">setup_application_variables</span><span class="p">(),</span>
    <span class="nv">Config</span><span class="p">.</span>

<span class="nf">end_per_suite</span><span class="p">(_</span><span class="nv">Config</span><span class="p">)</span> <span class="o">-&gt;</span>
    <span class="nn">application</span><span class="p">:</span><span class="nf">stop</span><span class="p">(</span><span class="n">pgo</span><span class="p">),</span>
    <span class="n">ok</span><span class="p">.</span>
</code></pre></div></div>

<p>This is the meaty goodness, here we create a migrated database from a template (I’ll explain
in the next section). Then initialize a connection to that database and store the details
in <code class="language-plaintext highlighter-rouge">Config</code>. Again, this is how you pass information to your end step.</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">init_per_testcase</span><span class="p">(_</span><span class="nv">TestCase</span><span class="p">,</span> <span class="nv">Config</span><span class="p">)</span> <span class="o">-&gt;</span>
    <span class="err">#</span><span class="p">{</span><span class="n">temporary_database_atom</span> <span class="p">:</span><span class="o">=</span> <span class="nv">DatabaseAtom</span><span class="p">,</span> <span class="n">temporary_pool_id</span> <span class="p">:</span><span class="o">=</span> <span class="nv">PoolId</span><span class="p">}</span> <span class="o">=</span>
        <span class="nn">util_tests</span><span class="p">:</span><span class="nf">create_migrated_database_pool</span><span class="p">(),</span>
    <span class="p">[{</span><span class="n">temporary_database_atom</span><span class="p">,</span> <span class="nv">DatabaseAtom</span><span class="p">},</span> <span class="p">{</span><span class="n">temporary_pool_id</span><span class="p">,</span> <span class="nv">PoolId</span><span class="p">}</span> <span class="p">|</span> <span class="nv">Config</span><span class="p">].</span>
</code></pre></div></div>

<p>Finally, we pull out the <code class="language-plaintext highlighter-rouge">Config</code> information and destroy the temporary database
and the connection.</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">end_per_testcase</span><span class="p">(_</span><span class="nv">TestCase</span><span class="p">,</span> <span class="nv">Config</span><span class="p">)</span> <span class="o">-&gt;</span>
    <span class="nv">DatabaseAtom</span> <span class="o">=</span> <span class="nn">proplists</span><span class="p">:</span><span class="nf">get_value</span><span class="p">(</span><span class="n">temporary_database_atom</span><span class="p">,</span> <span class="nv">Config</span><span class="p">),</span>
    <span class="nv">PoolId</span> <span class="o">=</span> <span class="nn">proplists</span><span class="p">:</span><span class="nf">get_value</span><span class="p">(</span><span class="n">temporary_pool_id</span><span class="p">,</span> <span class="nv">Config</span><span class="p">),</span>
    <span class="nn">util_tests</span><span class="p">:</span><span class="nf">drop_database_and_pool</span><span class="p">(</span><span class="nv">DatabaseAtom</span><span class="p">,</span> <span class="nv">PoolId</span><span class="p">).</span>
</code></pre></div></div>

<p>Voila, single use database per test set up and tore down. In this suite, I just
do a test that the number of tables in the migrated database contains seven or
more tables. That was just how many tables I had when I set this up.
Seven isn’t at all magical.</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">the_current_database_is_the_temporary_one_and_contains_public_tables</span><span class="p">(</span><span class="nv">Config</span><span class="p">)</span> <span class="o">-&gt;</span>
    <span class="err">#</span><span class="p">{</span><span class="n">command</span> <span class="p">:</span><span class="o">=</span> <span class="n">select</span><span class="p">,</span> <span class="n">num_rows</span> <span class="p">:</span><span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">rows</span> <span class="p">:</span><span class="o">=</span> <span class="p">[{</span><span class="nv">NumberPublicTables</span><span class="p">}]}</span> <span class="o">=</span> <span class="nn">pgo</span><span class="p">:</span><span class="k">query</span><span class="p">(</span>
        <span class="o">&lt;&lt;</span><span class="s">"select count(*) from information_schema.tables where table_schema = 'public'"</span><span class="o">&gt;&gt;</span>
    <span class="p">),</span>
    <span class="o">?</span><span class="nf">assert</span><span class="p">(</span><span class="nv">NumberPublicTables</span> <span class="o">&gt;=</span> <span class="mi">7</span><span class="p">),</span>

    <span class="nv">DatabaseAtom</span> <span class="o">=</span> <span class="nn">proplists</span><span class="p">:</span><span class="nf">get_value</span><span class="p">(</span><span class="n">temporary_database_atom</span><span class="p">,</span> <span class="nv">Config</span><span class="p">),</span>
    <span class="err">#</span><span class="p">{</span><span class="n">command</span> <span class="p">:</span><span class="o">=</span> <span class="n">select</span><span class="p">,</span> <span class="n">num_rows</span> <span class="p">:</span><span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">rows</span> <span class="p">:</span><span class="o">=</span> <span class="p">[{</span><span class="nv">CurrentDatabase</span><span class="p">}]}</span> <span class="o">=</span> <span class="nn">pgo</span><span class="p">:</span><span class="k">query</span><span class="p">(</span>
        <span class="o">&lt;&lt;</span><span class="s">"select current_database()"</span><span class="o">&gt;&gt;</span>
    <span class="p">),</span>
    <span class="o">?</span><span class="nf">assert</span><span class="p">(</span><span class="nv">CurrentDatabase</span> <span class="o">=:=</span> <span class="nf">atom_to_binary</span><span class="p">(</span><span class="nv">DatabaseAtom</span><span class="p">)).</span>
</code></pre></div></div>

<h2 id="getting-postgresql-in-github-actions-ci">Getting PostgreSQL in GitHub Actions CI</h2>

<p>I’ll go over more specific Erlang bits in the next section. First, let’s get
PostgreSQL in GitHub actions.</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">ikalnytskyi/action-setup-postgres@v6</span>
        <span class="na">id</span><span class="pi">:</span> <span class="s">postgres</span>
        <span class="na">with</span><span class="pi">:</span>
          <span class="na">username</span><span class="pi">:</span> <span class="s">my_app</span>
          <span class="na">password</span><span class="pi">:</span> <span class="s">my_app</span>
          <span class="na">database</span><span class="pi">:</span> <span class="s">my_app_template</span>
          <span class="na">port</span><span class="pi">:</span> <span class="m">5432</span>
</code></pre></div></div>

<p>Conveniently there is already a github action for this. The interesting part is
that I am defining the database as <code class="language-plaintext highlighter-rouge">my_app_template</code> which is just a separate
copy of my migrated database. This is because, locally, <code class="language-plaintext highlighter-rouge">my_app</code> is used to test
and I don’t want to copy any data from it every time I create a temporary database.
Migrating the template database is also easy,</p>

<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>      <span class="pi">-</span> <span class="na">uses</span><span class="pi">:</span> <span class="s">cachix/install-nix-action@v27</span>
        <span class="na">with</span><span class="pi">:</span>
          <span class="na">nix_path</span><span class="pi">:</span> <span class="s">nixpkgs=channel:nixos-unstable</span>
          <span class="na">github_access_token</span><span class="pi">:</span> <span class="s">${{ secrets.GITHUB_TOKEN }}</span>
      <span class="pi">-</span> <span class="na">run</span><span class="pi">:</span> <span class="s">nix-shell -p dbmate --run "unset PGSERVICEFILE &amp;&amp; dbmate up"</span>
        <span class="na">env</span><span class="pi">:</span>
          <span class="na">DATABASE_URL</span><span class="pi">:</span> <span class="s">${{ steps.postgres.outputs.connection-uri }}?sslmode=disable</span>
</code></pre></div></div>

<p>Here, I use <a href="https://nixos.org">nix</a> to get <a href="https://github.com/amacneil/dbmate">dbmate</a>.
Both of these tools are nice to use.
One of them is <strong>a lot</strong> harder than the other.</p>

<h2 id="internal-erlang-functions">Internal Erlang Functions</h2>

<p>I showed you the high level common test earlier. Some of the internals
are in this section,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">create_migrated_database_pool</span><span class="p">()</span> <span class="o">-&gt;</span>
    <span class="c">% Create a temporary database and initialize a connection to it
</span>    <span class="nv">DatabaseAtom</span> <span class="o">=</span> <span class="nn">util_pgo</span><span class="p">:</span><span class="nf">create_temporary_database</span><span class="p">(),</span>
    <span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">PoolId</span><span class="p">}</span> <span class="o">=</span> <span class="nn">util_pgo</span><span class="p">:</span><span class="nf">start_default_pool_with_name</span><span class="p">(</span><span class="nv">DatabaseAtom</span><span class="p">),</span>
    <span class="err">#</span><span class="p">{</span><span class="n">temporary_database_atom</span> <span class="o">=&gt;</span> <span class="nv">DatabaseAtom</span><span class="p">,</span> <span class="n">temporary_pool_id</span> <span class="o">=&gt;</span> <span class="nv">PoolId</span><span class="p">}.</span>
</code></pre></div></div>

<p>The implementation of the function in my per-test database and pool initializer,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">create_temporary_database</span><span class="p">()</span> <span class="o">-&gt;</span>
    <span class="nv">DatabaseName</span> <span class="o">=</span> <span class="nf">get_random_database_name</span><span class="p">(),</span>
    <span class="nv">DatabaseAtom</span> <span class="o">=</span> <span class="nb">list_to_atom</span><span class="p">(</span><span class="nv">DatabaseName</span><span class="p">),</span>
    <span class="nv">Cmd</span> <span class="o">=</span> <span class="s">"createdb "</span> <span class="o">++</span> <span class="nv">DatabaseName</span> <span class="o">++</span> <span class="s">" -T my_app_template"</span><span class="p">,</span>
    <span class="nv">Output</span> <span class="o">=</span> <span class="o">?</span><span class="nf">cmd</span><span class="p">(</span><span class="nv">Cmd</span><span class="p">),</span>
    <span class="nn">logger</span><span class="p">:</span><span class="nf">notice</span><span class="p">(</span><span class="err">#</span><span class="p">{</span>
        <span class="n">action</span> <span class="o">=&gt;</span> <span class="n">create_temporary_database</span><span class="p">,</span> <span class="n">cmd</span> <span class="o">=&gt;</span> <span class="nv">Cmd</span><span class="p">,</span> <span class="n">output</span> <span class="o">=&gt;</span> <span class="nv">Output</span>
    <span class="p">}),</span>
    <span class="nv">DatabaseAtom</span><span class="p">.</span>
</code></pre></div></div>

<p>I literally just shell out to <code class="language-plaintext highlighter-rouge">createdb</code>. The command macro is pretty slick.
Also, check out my <a href="https://www.youtube.com/watch?v=xMvwYtUkT0A">YouTube video</a> on the <code class="language-plaintext highlighter-rouge">logger</code> module.
Finally, we can start our connection via pgo,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">start_default_pool_with_name</span><span class="p">(</span><span class="nv">Atom</span><span class="p">)</span> <span class="o">-&gt;</span>
    <span class="nn">pgo</span><span class="p">:</span><span class="nf">start_pool</span><span class="p">(</span>
        <span class="n">default</span><span class="p">,</span>
        <span class="err">#</span><span class="p">{</span>
            <span class="n">pool_size</span> <span class="o">=&gt;</span> <span class="mi">1</span><span class="p">,</span>
            <span class="n">host</span> <span class="o">=&gt;</span> <span class="nn">environment</span><span class="p">:</span><span class="nf">get_application_variable</span><span class="p">(</span><span class="n">pgo_host</span><span class="p">),</span>
            <span class="n">user</span> <span class="o">=&gt;</span> <span class="nn">environment</span><span class="p">:</span><span class="nf">get_application_variable</span><span class="p">(</span><span class="n">pgo_user</span><span class="p">),</span>
            <span class="n">database</span> <span class="o">=&gt;</span> <span class="nf">atom_to_binary</span><span class="p">(</span><span class="nv">Atom</span><span class="p">),</span>
            <span class="n">password</span> <span class="o">=&gt;</span> <span class="nn">environment</span><span class="p">:</span><span class="nf">get_application_variable</span><span class="p">(</span><span class="n">pgo_password</span><span class="p">)</span>
        <span class="p">}</span>
    <span class="p">).</span>
</code></pre></div></div>

<p>At our end step, we just shell out to <code class="language-plaintext highlighter-rouge">dropdb</code> and kill the pool with,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="n">ok</span> <span class="o">=</span> <span class="nn">supervisor</span><span class="p">:</span><span class="nf">terminate_child</span><span class="p">(</span><span class="n">pgo_sup</span><span class="p">,</span> <span class="nv">PoolId</span><span class="p">),</span>
</code></pre></div></div>

<h2 id="summary">Summary</h2>

<p>This was a super interesting thing to set up myself. It isn’t a ton of work
and there are GitHub actions to help you out. I am really enjoying my time with
Erlang but testing even simple database actions is really important. I found
that almost all of my query code was wrong at first. The project I set this up for is
currently private but feel free to ask me questions on <a href="https://bsky.app/profile/chiroptical.dev">BlueSky</a>.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Overview]]></summary></entry><entry><title type="html">Getting started with Erlang’s `maybe_expr`</title><link href="https://chiroptical.github.io/posts/2024-03-04-erlang-maybe_expr.html" rel="alternate" type="text/html" title="Getting started with Erlang’s `maybe_expr`" /><published>2024-03-04T00:00:00+00:00</published><updated>2024-03-04T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/erlang-maybe_expr</id><content type="html" xml:base="https://chiroptical.github.io/posts/2024-03-04-erlang-maybe_expr.html"><![CDATA[<h2 id="assumptions">Assumptions</h2>

<p>You are using <a href="https://rebar3.org">rebar3</a> to build your project. You are using OTP 25.</p>

<h2 id="introduction">Introduction</h2>

<p>I am an Erlang beginner and I am currently building a Slack bot to learn more.
Here is some code I wrote recently,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">ChannelId</span><span class="p">}</span> <span class="o">=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"channel"</span><span class="o">&gt;&gt;</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"id"</span><span class="o">&gt;&gt;</span><span class="p">],</span> <span class="nv">Payload</span><span class="p">),</span>
<span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">UserId</span><span class="p">}</span> <span class="o">=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"user"</span><span class="o">&gt;&gt;</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"id"</span><span class="o">&gt;&gt;</span><span class="p">],</span> <span class="nv">Payload</span><span class="p">),</span>
<span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">TeamId</span><span class="p">}</span> <span class="o">=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"team"</span><span class="o">&gt;&gt;</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"id"</span><span class="o">&gt;&gt;</span><span class="p">],</span> <span class="nv">Payload</span><span class="p">),</span>
<span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">ResponseUrl</span><span class="p">}</span> <span class="o">=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"response_url"</span><span class="o">&gt;&gt;</span><span class="p">],</span> <span class="nv">Payload</span><span class="p">),</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">Payload</code> here is a decoded JSON body from Slack. The <code class="language-plaintext highlighter-rouge">map_utils:recursive_get/2</code> function
takes the path to a JSON entry and extracts it if possible, given this JSON</p>

<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
  </span><span class="nl">"channel"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
    </span><span class="nl">"id"</span><span class="p">:</span><span class="w"> </span><span class="s2">"value"</span><span class="w">
  </span><span class="p">}</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>

<p>If we ran this JSON through my HTTP handlers, this code would succeed,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"value"</span><span class="o">&gt;&gt;</span><span class="p">}</span> <span class="o">=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"channel"</span><span class="o">&gt;&gt;</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"id"</span><span class="o">&gt;&gt;</span><span class="p">]),</span>
<span class="p">{</span><span class="n">error</span><span class="p">,</span> <span class="n">not_found</span><span class="p">}</span> <span class="o">=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"hello"</span><span class="o">&gt;&gt;</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"world"</span><span class="o">&gt;&gt;</span><span class="p">]),</span>
</code></pre></div></div>

<p>When the <code class="language-plaintext highlighter-rouge">ChannelId</code>, <code class="language-plaintext highlighter-rouge">UserId</code>, etc are all extracted from the <code class="language-plaintext highlighter-rouge">Payload</code>
properly everything is great. However, if any of the pattern matches fails
everything seems to get dropped into the void. This is obviously problematic
when you are building an application. Thankfully, I discovered <code class="language-plaintext highlighter-rouge">maybe_expr</code>!</p>

<p>With <code class="language-plaintext highlighter-rouge">maybe_expr</code>, the code will look more like this,</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">-</span><span class="ni">record</span><span class="p">(</span><span class="nl">interact_payload</span><span class="p">,</span> <span class="p">{</span><span class="n">channel_id</span><span class="p">,</span> <span class="n">user_id</span><span class="p">,</span> <span class="n">team_id</span><span class="p">,</span> <span class="n">response_url</span><span class="p">})</span>

<span class="c">% ...
</span>
<span class="n">maybe</span>
  <span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">ChannelId</span><span class="p">}</span> <span class="o">?=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"channel"</span><span class="o">&gt;&gt;</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"id"</span><span class="o">&gt;&gt;</span><span class="p">],</span> <span class="nv">Payload</span><span class="p">),</span>
  <span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">UserId</span><span class="p">}</span> <span class="o">?=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"user"</span><span class="o">&gt;&gt;</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"id"</span><span class="o">&gt;&gt;</span><span class="p">],</span> <span class="nv">Payload</span><span class="p">),</span>
  <span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">TeamId</span><span class="p">}</span> <span class="o">?=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"team"</span><span class="o">&gt;&gt;</span><span class="p">,</span> <span class="o">&lt;&lt;</span><span class="s">"id"</span><span class="o">&gt;&gt;</span><span class="p">],</span> <span class="nv">Payload</span><span class="p">),</span>
  <span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nv">ResponseUrl</span><span class="p">}</span> <span class="o">?=</span> <span class="nn">map_utils</span><span class="p">:</span><span class="nf">recursive_get</span><span class="p">([</span><span class="o">&lt;&lt;</span><span class="s">"response_url"</span><span class="o">&gt;&gt;</span><span class="p">],</span> <span class="nv">Payload</span><span class="p">)</span>
  <span class="p">{</span><span class="n">ok</span><span class="p">,</span> <span class="nl">#interact_payload</span><span class="p">{</span><span class="n">channel_id</span> <span class="o">=</span> <span class="nv">ChannelId</span><span class="p">,</span> <span class="n">user_id</span> <span class="o">=</span> <span class="nv">UserId</span><span class="p">,</span> <span class="n">team_id</span> <span class="o">=</span> <span class="nv">TeamId</span><span class="p">,</span> <span class="n">response_url</span> <span class="o">=</span> <span class="nv">ResponseUrl</span><span class="p">}}</span>
<span class="n">else</span>
  <span class="p">{</span><span class="n">error</span><span class="p">,</span> <span class="n">not_found</span><span class="p">}</span> <span class="o">-&gt;</span>
    <span class="nn">logger</span><span class="p">:</span><span class="nf">error</span><span class="p">(...),</span>
    <span class="p">{</span><span class="n">error</span><span class="p">,</span> <span class="n">not_found</span><span class="p">};</span>
  <span class="p">{</span><span class="n">error</span><span class="p">,</span> <span class="n">not_found</span><span class="p">,</span> <span class="nv">Reason</span><span class="p">}</span> <span class="o">-&gt;</span>
    <span class="nn">logger</span><span class="p">:</span><span class="nf">error</span><span class="p">(...),</span>
    <span class="p">{</span><span class="n">error</span><span class="p">,</span> <span class="n">not_found</span><span class="p">}</span>
<span class="k">end</span><span class="p">,</span>
</code></pre></div></div>

<p>Instead of dropping anything into the void, the <code class="language-plaintext highlighter-rouge">else</code> clause can be used to pattern
match out any failure cases. Here, we match <code class="language-plaintext highlighter-rouge">{error, not_found}</code> and <code class="language-plaintext highlighter-rouge">{error,
not_found, Reason}</code> and log that we had an unexpected error.</p>

<p>This feature is currently <a href="https://www.erlang.org/doc/reference_manual/expressions#maybe">“experimental” in OTP 25</a>. However,
it is becoming standardized over the next few OTP releases. See this
<a href="https://www.erlang.org/blog/otp-26-highlights/#no-need-to-enable-feature-maybe-in-the-runtime-system">highlight</a> for more information.</p>

<h2 id="setting-up-rebar3">Setting up rebar3</h2>

<p>Credit to <a href="https://erlangforums.com/t/how-to-enable-maybe-expr/2154">this forum entry</a> for the details. With OTP 25, first
create the file <code class="language-plaintext highlighter-rouge">config/vm.args</code> if it doesn’t exist and add,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>-enable-feature maybe_expr
</code></pre></div></div>

<p>Then set this in your environment,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>export ERL_FLAGS="-args_file config/vm.args"
</code></pre></div></div>

<p>Or, prepend <code class="language-plaintext highlighter-rouge">ERL_FLAGS="-args_file config/vm.args"</code> to your <code class="language-plaintext highlighter-rouge">rebar3</code> commands.
Reminder, you can skip this step in OTP 26.</p>

<h2 id="enabling-the-feature">Enabling the feature</h2>

<p>In your Erlang files you only need to add (after your module definition),</p>

<div class="language-erlang highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">-</span><span class="ni">module</span><span class="p">(...).</span>
<span class="p">-</span><span class="ni">feature</span><span class="p">(</span><span class="n">maybe_expr</span><span class="p">,</span> <span class="n">enable</span><span class="p">).</span>
</code></pre></div></div>

<p>Done. Supposedly in <a href="https://www.erlang.org/news/167#compiler-and-jit-improvements">OTP 27</a> you won’t need to do either of these steps!</p>

<h2 id="more-information">More information</h2>

<p>You can read the Erlang Enhancement Process proposal <a href="https://www.erlang.org/eeps/eep-0049">here</a>.</p>

<p>If you’ve ever written Haskell before this is essentially <a href="https://hackage.haskell.org/package/transformers-0.6.1.1/docs/Control-Monad-Trans-Except.html#g:2"><code class="language-plaintext highlighter-rouge">ExceptT e IO
a</code></a> where the <code class="language-plaintext highlighter-rouge">e</code> can be literally anything. It is your job in Erlang
to catch all the cases. You can add type checking to your Erlang code with
something like <a href="https://github.com/WhatsApp/eqwalizer">eqWAlizer</a> and type annotations via dialyzer. I was
first exposed to type annotations in <a href="https://learnyousomeerlang.com/dialyzer#plt">LYAH’s dialyzer
introduction</a>.</p>

<p>If there is anything you are curious about in Erlang, please ask me about it on
<a href="https://bsky.app/profile/chiroptical.dev">BlueSky</a> or the <a href="https://erlef.org/slack-invite/erlanger">Erlanger’s Slack</a>. I would like to
write more blog posts and learn more about Erlang.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Assumptions]]></summary></entry><entry><title type="html">First day with typst, a markup based typesetting system</title><link href="https://chiroptical.github.io/posts/2023-03-31-first-day-with-typst.html" rel="alternate" type="text/html" title="First day with typst, a markup based typesetting system" /><published>2023-03-31T00:00:00+00:00</published><updated>2023-03-31T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/first-day-with-typst</id><content type="html" xml:base="https://chiroptical.github.io/posts/2023-03-31-first-day-with-typst.html"><![CDATA[<p>I came across <a href="https://github.com/typst/typst">typst</a> recently which looks like
an interesting replacement to LaTeX. I don’t really do much collaborative
editing anymore, but I really enjoy plain text presentations. I tried
<a href="https://docs.racket-lang.org/pollen/">pollen</a> as well, but I didn’t like the
unicode symbols. What was my first presentation like using <code class="language-plaintext highlighter-rouge">typst</code>?</p>

<p><code class="language-plaintext highlighter-rouge">typst</code> is available on <a href="https://search.nixos.org/packages?channel=unstable&amp;from=0&amp;size=50&amp;sort=relevance&amp;type=packages&amp;query=typst">the unstable nix
channel</a>
and you can likely get it with <code class="language-plaintext highlighter-rouge">nix-shell -p typst</code> or follow the instructions
on <a href="https://github.com/typst/typst">their github</a>.</p>

<p>One annoying thing about LaTeX is you have to compile a bunch of times for your
PDF to be correct. With <code class="language-plaintext highlighter-rouge">typst</code>, you can <code class="language-plaintext highlighter-rouge">typst -w document.typ</code> and it will
watch the document for changes and recompile automatically. This is a really
nice productivity boost.</p>

<p>Setting up the presentation,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#set page(                                                                 
  paper: "presentation-16-9",    
  margin: (    
    rest: 25pt    
  )    
)   
</code></pre></div></div>

<p>Here, we are setting parameters for the
<a href="https://typst.app/docs/reference/layout/page/">page</a>. <code class="language-plaintext highlighter-rouge">#</code> denotes a “code
expression”. I believe I could also build my own template to define margins, spacing,
font, etc. in a separate file.</p>

<p>Next, the font,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#set text(    
  font: "JetBrains Mono",    
  size: 22pt    
)
</code></pre></div></div>

<p>This syntax is a bit odd, but it is syntax and LaTeX isn’t necessarily nicer in
any way. You can lay out a slide like so,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>= The slides title

// The slides content

#pagebreak()
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">=</code> denotes a header, you can generate smaller headers with additional <code class="language-plaintext highlighter-rouge">=</code>,
i.e. <code class="language-plaintext highlighter-rouge">===</code>. The <code class="language-plaintext highlighter-rouge">//</code> denotes a comment, most of what you need is from
markdown, see <a href="https://typst.app/docs/reference/syntax/">the syntax guide</a>.
Interestingly, you can make this into a named function,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>let slide(title, content) = [
  = #title
  #content
  #pagebreak()
]
</code></pre></div></div>

<p>The function syntax is a bit weird to me, but I also don’t fully understand the
type system yet. As an example, here is another function,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  #let fig(location, width, gap, caption) = [
    #figure(
      image(location, width: width),
      numbering: none,
      gap: gap,
      caption: caption
    )
  ]
</code></pre></div></div>

<p>Note the difference in how I refer to the parameters in the body. I think the
former <code class="language-plaintext highlighter-rouge">#x</code> are inserting “content blocks” and the latter are plain values and
don’t require the <code class="language-plaintext highlighter-rouge">#</code>. Not exactly sure yet.</p>

<p>From here, you could generate a slide with a figure pretty easy.</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#slide(
  [The slides title],
  [
    - Some unordered list item
    - Some other unordered list item
    fig(
      "figures/image.png", 
      350pt, // the width of the image, see function definition
      -2pt, // the captions are a bit far away from the images by default
      [ The caption for the figure. ]
    )
  ]
)
</code></pre></div></div>

<p>From here, you can build a basic presentation! Pretty cool.</p>

<p>I also wrote two other functions for links:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>#let l(location) = link(location)[#text(blue)[#location]]
#let ld(location, description) = link(location)[#text(blue)[#description]]
</code></pre></div></div>

<p>I did try a two column <code class="language-plaintext highlighter-rouge">#grid</code> but the alignment was a bit wonky. I would like
to spend a bit more time handling columnar layouts before attempting to show
some code. Let me know what you think on <a href="https://bsky.app/profile/chiroptical.dev">BlueSky</a></p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[I came across typst recently which looks like an interesting replacement to LaTeX. I don’t really do much collaborative editing anymore, but I really enjoy plain text presentations. I tried pollen as well, but I didn’t like the unicode symbols. What was my first presentation like using typst?]]></summary></entry><entry><title type="html">Discarding monadic results in Haskell</title><link href="https://chiroptical.github.io/posts/2021-09-01-discarding-monadic-results-in-haskell.html" rel="alternate" type="text/html" title="Discarding monadic results in Haskell" /><published>2021-09-01T00:00:00+00:00</published><updated>2021-09-01T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/discarding-monadic-results-in-haskell</id><content type="html" xml:base="https://chiroptical.github.io/posts/2021-09-01-discarding-monadic-results-in-haskell.html"><![CDATA[<h1 id="discarding-monadic-results-in-haskell">Discarding Monadic Results in Haskell</h1>

<p>I recently ran this poll on
<a href="https://twitter.com/chiroptical/status/1433059574370689027">Twitter</a>. The
original poll and results,</p>

<p><img src="/assets/discarding-monadic-results-poll.png" alt="poll" /></p>

<p>I wasn’t expecting much from this poll but the comments turned out to be fantastic!
Let’s summarize the problem, options, and discuss them a bit. The focus of the
discussion will be if <strong>I would use it in my personal project</strong>. It isn’t a suggestion.</p>

<h2 id="motivation">Motivation</h2>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">module</span> <span class="nn">Main</span> <span class="kr">where</span>    
    
<span class="n">f</span> <span class="o">::</span> <span class="kt">IO</span> <span class="kt">Int</span>    
<span class="n">f</span> <span class="o">=</span> <span class="n">pure</span> <span class="mi">1</span>    
    
<span class="n">main</span> <span class="o">::</span> <span class="kt">IO</span> <span class="nb">()</span>    
<span class="n">main</span> <span class="o">=</span> <span class="kr">do</span>    
  <span class="c1">-- business...    </span>
  <span class="n">f</span>    
  <span class="c1">-- more business...    </span>
  <span class="n">pure</span> <span class="nb">()</span>
</code></pre></div></div>

<p>The following warning is generated when you compile this with <code class="language-plaintext highlighter-rouge">-Wall</code>,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>src/Main.hs:9:3: warning: [-Wunused-do-bind]
    A do-notation statement discarded a result of type ‘Int’
    Suppress this warning by saying ‘_ &lt;- f’
  |
9 |   f
  |   ^
</code></pre></div></div>

<p>Typically, I also use <code class="language-plaintext highlighter-rouge">-Werror</code> and therefore the warning becomes an error. What are our options in this case?</p>

<h2 id="options">Options</h2>

<p>We need to discard the result of <code class="language-plaintext highlighter-rouge">f</code>. Here are all the suggested solutions (attributed to the first suggester),</p>

<ul>
  <li>Disable the warning <code class="language-plaintext highlighter-rouge">-Wno-unused-do-bind</code> <a href="https://twitter.com/TechnoEmpress/status/1433169858477371392">@TechnoEmpress</a></li>
  <li><code class="language-plaintext highlighter-rouge">void f</code> (in the poll)</li>
  <li><code class="language-plaintext highlighter-rouge">() &lt;$ f</code> <a href="https://twitter.com/alex_pir/status/1433279377786163200">@alex_pir</a></li>
  <li><code class="language-plaintext highlighter-rouge">_ &lt;- f</code> (in the poll)</li>
  <li><code class="language-plaintext highlighter-rouge">_ ← f</code> <a href="https://twitter.com/toastal/status/1433075730347278336">@toastal</a></li>
  <li><code class="language-plaintext highlighter-rouge">_descriptiveName &lt;- f</code> <a href="https://twitter.com/MxLambda/status/1433072010846998532">@MxLambda</a></li>
  <li><code class="language-plaintext highlighter-rouge">(_ :: ResultType) &lt;- f </code>, in this case <code class="language-plaintext highlighter-rouge">Int</code> <a href="https://twitter.com/vincenthz/status/1433387638275260423">@vincenthz</a></li>
</ul>

<h2 id="breakdown">Breakdown</h2>

<p>Let’s look at a few of the options a bit.</p>

<h3 id="void">void</h3>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">void</span> <span class="o">::</span> <span class="kt">Functor</span> <span class="n">f</span> <span class="o">=&gt;</span> <span class="n">f</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">f</span> <span class="nb">()</span>
</code></pre></div></div>

<p>I have always used this in my personal projects. It gets the job done, but isn’t particularly satisfying (hence the poll).
The win here is that it only requires a <code class="language-plaintext highlighter-rouge">Functor</code> constraint and can be used beyond <code class="language-plaintext highlighter-rouge">do</code> notation.
I wonder if <code class="language-plaintext highlighter-rouge">void</code> would be more compelling if it was named differently? Maybe <code class="language-plaintext highlighter-rouge">discard</code> or <code class="language-plaintext highlighter-rouge">ignore</code>?</p>

<h3 id="the-const-equivalent">The const equivalent</h3>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="o">&lt;$</span><span class="p">)</span> <span class="o">::</span> <span class="kt">Functor</span> <span class="n">f</span> <span class="o">=&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">f</span> <span class="n">b</span> <span class="o">-&gt;</span> <span class="n">f</span> <span class="n">a</span>
<span class="p">(</span><span class="o">&lt;$</span><span class="p">)</span> <span class="o">=</span> <span class="n">fmap</span> <span class="o">.</span> <span class="n">const</span>
</code></pre></div></div>

<p>This is <code class="language-plaintext highlighter-rouge">const</code> lifted into a functorial context. It is more flexible than <code class="language-plaintext highlighter-rouge">void</code> and useful for the same reasons.
It is provided, for free, by the Functor typeclass and is one I often forget about. That being said, I don’t feel
particularly compelled to start using <code class="language-plaintext highlighter-rouge">() &lt;$ ...</code> over <code class="language-plaintext highlighter-rouge">void</code>.</p>

<h3 id="underscores">Underscores</h3>

<p>The options,</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kr">_</span> <span class="o">&lt;-</span> <span class="n">f</span>
<span class="p">(</span><span class="kr">_</span> <span class="o">::</span> <span class="kt">Int</span><span class="p">)</span> <span class="o">&lt;-</span> <span class="n">f</span>
<span class="n">_descriptiveName</span> <span class="o">&lt;-</span> <span class="n">f</span>
</code></pre></div></div>

<p>The first line is saying “match something, but I don’t care what”. This is equivalent to <code class="language-plaintext highlighter-rouge">void</code> but preferred by more respondents.
There is one exception to this preference (expressed in the responses as well),</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>do
  -- business...
  _ &lt;- finalMonadicComputation
  pure ()
</code></pre></div></div>

<p>I personally think this should be <code class="language-plaintext highlighter-rouge">void</code> in almost all cases.
The latter two lines are much more interesting to consider and make context even more important.
Specifying the underscore’s type, i.e. <code class="language-plaintext highlighter-rouge">_ :: Int</code>, does add some additional type safety if the monadic computation changes.
However, in most cases, changing the monadic computation would at least point me to the underscore (thanks GHC)
so I can reconsider my choices. Adding a descriptive name is never a bad thing, but sometimes it is difficult to come
up with a <strong>good</strong> name or the function names are clear enough. I think both of these are interesting and I will probably
use some variation of them in the future.</p>

<p>Bonus: with <code class="language-plaintext highlighter-rouge">ScopedTypeVariables</code> you can remove the parentheses.</p>

<h3 id="unicode">Unicode</h3>

<p>Honestly, I don’t even know how to enter a unicode arrow on my keyboard. Cool suggestion nonetheless.</p>

<h3 id="disable-the-warning">Disable the warning</h3>

<p>Here I am appeasing the compiler for <code class="language-plaintext highlighter-rouge">-Wall -Werror</code> and Hécate is playing an entirely different game.
I think this is interesting and I might try it out in my personal projects. However, you <strong>do</strong> lose a signal
that the monadic computation returns something. In Haskell, we often use <code class="language-plaintext highlighter-rouge">descriptiveFunctionName_</code> to
indicate that a function returns <code class="language-plaintext highlighter-rouge">()</code> and if you follow that convention you could use that as a signal.
Do I really need this signal? I am not so sure anymore.</p>

<h2 id="wrapping-up">Wrapping up</h2>

<p>This poll generated a surprising response. The results were both fun,
interesting, and will hopefully make me think more carefully about context. I
hope you enjoyed it as much as I did.</p>

<p>Find typos or have suggestions? My DMs are always open
<a href="https://bsky.app/profile/chiroptical.dev">@chiroptical.dev</a>.</p>

<p>Like the content? Follow me on <a href="https://twitch.tv/chiroptical">Twitch</a> and
subscribe on <a href="https://youtube.com/chiroptical">Youtube</a></p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Discarding Monadic Results in Haskell]]></summary></entry><entry><title type="html">Simple Scaleable Preprocessing with PyTorch and Ray - 0</title><link href="https://chiroptical.github.io/posts/2020-05-20-simple-scaleable-preprocessing-with-pytorch-and-ray.html" rel="alternate" type="text/html" title="Simple Scaleable Preprocessing with PyTorch and Ray - 0" /><published>2020-05-20T00:00:00+00:00</published><updated>2020-05-20T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/simple-scaleable-preprocessing-with-pytorch-and-ray</id><content type="html" xml:base="https://chiroptical.github.io/posts/2020-05-20-simple-scaleable-preprocessing-with-pytorch-and-ray.html"><![CDATA[<h2 id="simple-scaleable-preprocessing-with-pytorch-and-ray">Simple Scaleable Preprocessing With Pytorch and Ray</h2>

<h4 id="background">Background</h4>

<p>I have been using <a href="https://pytorch.org/">PyTorch</a> for a few months now and I
really like the <code class="language-plaintext highlighter-rouge">Dataset</code> and <code class="language-plaintext highlighter-rouge">DataLoader</code> workflow (see
<a href="https://pytorch.org/docs/stable/data.html"><code class="language-plaintext highlighter-rouge">torch.utils.data</code></a>). I realized I
might be able to use this workflow for every step in my Machine Learning
pipeline, i.e. preprocessing, training, and inference. I further realized I
could use <a href="https://docs.ray.io/en/stable/index.html">Ray</a> to coordinate
multi-node parallelism with little changes to my original code.</p>

<p><strong>Escape Hatch</strong>: if you would rather explore the code with no explanation
there is a <a href="https://github.com/chiroptical/pytorch-ray-workflow/blob/master/PyTorchDatasetExample.ipynb">Jupyter Notebook on
Github</a></p>

<p>I believe most folks are using <code class="language-plaintext highlighter-rouge">Dataset/DataLoader</code> to handle training and
inference pipelines but let’s consider a more general preprocessing workflow. A
data scientist needs to write a function which processes their entire data set,
the function has the approximate signature:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>InputFile -&gt; (OutputFiles, Metadata)
</code></pre></div></div>

<p>Here, <code class="language-plaintext highlighter-rouge">InputFile</code> is an input file in your dataset. The function may produce
one, or more, <code class="language-plaintext highlighter-rouge">OutputFiles</code> and some <code class="language-plaintext highlighter-rouge">Metadata</code> related to the operation
performed. As a practical example, I often have to split large audio files into
multiple audio files of a fixed size and retain some metadata (source audio,
destination audio, labels).</p>

<p>In this blog post, I’ll discuss how to get PyTorch’s <code class="language-plaintext highlighter-rouge">DataSet</code> and <code class="language-plaintext highlighter-rouge">DataLoader</code>
workflow running in parallel for this general use case. I will also go over
some of the mistakes I made while first exploring this workflow. I will assume
the reader knows basic Python.</p>

<h3 id="why-should-you-care">Why should you care?</h3>

<p>I believe this workflow is really easy to teach to beginners. A user only needs
to know how to write a function to process an input file and the relationship
between batches and parallelism. With the exception of the <code class="language-plaintext highlighter-rouge">collate_fn</code>
(explained later) the code is essentially boilerplate. If you can implement a
<code class="language-plaintext highlighter-rouge">Dataset</code> the parallelism comes almost for free which is a <strong>massive</strong> win for
beginners.</p>

<h4 id="up-and-running">Up and Running</h4>

<p>I am going to build an example data set which mimics the audio splitting
example I introduced. I will have a <code class="language-plaintext highlighter-rouge">dataset.csv</code> file which contains the
following:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>input
a.txt
b.txt
c.txt
d.txt
</code></pre></div></div>

<p>Each TXT file will contain a word (<code class="language-plaintext highlighter-rouge">simple</code>, <code class="language-plaintext highlighter-rouge">scaleable</code>, <code class="language-plaintext highlighter-rouge">preprocessing</code>, and
<code class="language-plaintext highlighter-rouge">pytorch</code> respectively). The files will be located in an <code class="language-plaintext highlighter-rouge">inputs/</code> directory.
The goal is to split each word into parts of a certain number of characters and
overlap, e.g.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">=</span> <span class="s">"hello"</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">split_word</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">num_chars</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">overlap</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">b</span> <span class="o">==</span> <span class="p">[</span><span class="s">"he"</span><span class="p">,</span> <span class="s">"el"</span><span class="p">,</span> <span class="s">"ll"</span><span class="p">,</span> <span class="s">"lo"</span><span class="p">]</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">split_word</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">num_chars</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">overlap</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">c</span> <span class="o">==</span> <span class="p">[</span><span class="s">"hel"</span><span class="p">,</span> <span class="s">"ell"</span><span class="p">,</span> <span class="s">"llo"</span><span class="p">]</span>
</code></pre></div></div>

<p>We can build a <code class="language-plaintext highlighter-rouge">Dataset</code> which performs this action on all of the input files.
First, let’s generate a list of input files. I’ll use the built-in CSV library:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">csv</span>

<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s">"dataset.csv"</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">csv_file</span><span class="p">:</span>
    <span class="n">reader</span> <span class="o">=</span> <span class="n">csv</span><span class="p">.</span><span class="n">DictReader</span><span class="p">(</span><span class="n">csv_file</span><span class="p">)</span>
    <span class="n">input_files</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s">"inputs/</span><span class="si">{</span><span class="n">row</span><span class="p">[</span><span class="s">'input'</span><span class="p">]</span><span class="si">}</span><span class="s">"</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="n">reader</span><span class="p">]</span>

<span class="k">assert</span> <span class="n">input_files</span> <span class="o">==</span> <span class="p">[</span><span class="s">"inputs/a.txt"</span><span class="p">,</span> <span class="s">"inputs/b.txt"</span><span class="p">,</span> <span class="s">"inputs/c.txt"</span><span class="p">,</span> <span class="s">"inputs/d.txt"</span><span class="p">]</span>
</code></pre></div></div>

<p>To use <code class="language-plaintext highlighter-rouge">Dataset</code>, you’ll need PyTorch (e.g. <code class="language-plaintext highlighter-rouge">pip3 install torch==1.5.0</code>)</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">torch.utils.data</span> <span class="kn">import</span> <span class="n">Dataset</span>

<span class="k">class</span> <span class="nc">WordSplitter</span><span class="p">(</span><span class="n">Dataset</span><span class="p">):</span>
    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">inputs</span><span class="p">,</span> <span class="n">num_chars</span><span class="o">=</span><span class="mi">2</span><span class="p">,</span> <span class="n">overlap</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">inputs</span> <span class="o">=</span> <span class="n">inputs</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">num_chars</span> <span class="o">=</span> <span class="n">num_chars</span>
        <span class="bp">self</span><span class="p">.</span><span class="n">overlap</span> <span class="o">=</span> <span class="n">overlap</span>
        
    <span class="k">def</span> <span class="nf">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
        <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">inputs</span><span class="p">)</span>
    
    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">idx</span><span class="p">):</span>
        <span class="n">filename</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">inputs</span><span class="p">[</span><span class="n">idx</span><span class="p">]</span>
        
        <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="n">filename</span><span class="p">,</span> <span class="s">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
            <span class="n">word</span> <span class="o">=</span> <span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">().</span><span class="n">strip</span><span class="p">()</span>
        
        <span class="k">return</span> <span class="n">split_word</span><span class="p">(</span>
            <span class="n">word</span><span class="p">,</span>
            <span class="n">num_chars</span><span class="o">=</span><span class="bp">self</span><span class="p">.</span><span class="n">num_chars</span><span class="p">,</span>
            <span class="n">overlap</span><span class="o">=</span><span class="bp">self</span><span class="p">.</span><span class="n">overlap</span>
        <span class="p">)</span>
</code></pre></div></div>

<p>For the <code class="language-plaintext highlighter-rouge">Dataset</code> to work, we need to define 3 “dunder” methods <code class="language-plaintext highlighter-rouge">__init__,
__len__, and __getitem</code>. The <code class="language-plaintext highlighter-rouge">__init__</code> function stores the input files and
parameters needed to run <code class="language-plaintext highlighter-rouge">split_word</code>. The <code class="language-plaintext highlighter-rouge">__len__</code> function returns the
length of <code class="language-plaintext highlighter-rouge">input_files</code>. The <code class="language-plaintext highlighter-rouge">__getitem__</code> function is where the computation
happens. First, we extract the file at the given index. Second, we read the
word from the file and remove any whitespace sorrounding the word. Finally, we
feed our word to <code class="language-plaintext highlighter-rouge">split_word</code> with the appropriate parameters. Let’s see if it
works:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">word_splitter</span> <span class="o">=</span> <span class="n">WordSplitter</span><span class="p">(</span><span class="n">input_files</span><span class="p">,</span> <span class="n">num_chars</span><span class="o">=</span><span class="mi">3</span><span class="p">,</span> <span class="n">overlap</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
<span class="k">assert</span> <span class="n">word_splitter</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">==</span> <span class="p">[</span><span class="s">'sim'</span><span class="p">,</span> <span class="s">'imp'</span><span class="p">,</span> <span class="s">'mpl'</span><span class="p">,</span> <span class="s">'ple'</span><span class="p">]</span>
</code></pre></div></div>

<p>Awesome. It is really important to make sure your <code class="language-plaintext highlighter-rouge">Dataset</code> works before moving
on to the next steps. Remember our signature from before:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>InputFile -&gt; (OutputFiles, Metadata)
</code></pre></div></div>

<p>Think of the <code class="language-plaintext highlighter-rouge">__getitem__</code> method in <code class="language-plaintext highlighter-rouge">WordSplitter</code> as inputting an
<code class="language-plaintext highlighter-rouge">InputFile</code>, not writing any <code class="language-plaintext highlighter-rouge">OutputFiles</code>, and producing <code class="language-plaintext highlighter-rouge">Metadata</code> related to
the operation. In the realistic audio splitting example the <code class="language-plaintext highlighter-rouge">OutputFiles</code> could
be written to an <code class="language-plaintext highlighter-rouge">outputs/</code> directory. We can now wrap this into a <code class="language-plaintext highlighter-rouge">DataLoader</code>
and run our analysis in parallel!</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">torch.utils.data</span> <span class="kn">import</span> <span class="n">DataLoader</span>

<span class="n">loader</span> <span class="o">=</span> <span class="n">DataLoader</span><span class="p">(</span>
    <span class="n">word_splitter</span><span class="p">,</span>
    <span class="n">batch_size</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
    <span class="n">shuffle</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span>
    <span class="n">num_workers</span><span class="o">=</span><span class="nb">len</span><span class="p">(</span><span class="n">word_splitter</span><span class="p">),</span>
<span class="p">)</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">DataLoader</code> bundles our work into batches to be operated on. The
<code class="language-plaintext highlighter-rouge">DataLoader</code> takes in the <code class="language-plaintext highlighter-rouge">word_splitter</code> <code class="language-plaintext highlighter-rouge">Dataset</code> object we initialized
previously. When we set <code class="language-plaintext highlighter-rouge">batch_size=1</code>, the <code class="language-plaintext highlighter-rouge">loader</code> will split our work into 4
total batches where each batch contains 1 file (<code class="language-plaintext highlighter-rouge">batch_size=2</code> means 2 batches
each with 2 files). With 4 batches it is possible to split the work over 4
cores on our machine by setting <code class="language-plaintext highlighter-rouge">num_workers=len(word_splitter)</code>. <strong>Important:
with <code class="language-plaintext highlighter-rouge">batch_size=4</code> there is only 1 batch to process and therefore no
parallelism can be extracted (i.e. setting <code class="language-plaintext highlighter-rouge">num_workers</code> will have no
effect)</strong>. The <code class="language-plaintext highlighter-rouge">shuffle=False</code>  argument asks the loader to process inputs in
order (the default). The <code class="language-plaintext highlighter-rouge">loader</code> object behaves like other iterators, i.e. we
can print the results in a <code class="language-plaintext highlighter-rouge">for</code> loop:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">metadata</span> <span class="ow">in</span> <span class="n">loader</span><span class="p">:</span>
    <span class="k">print</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span>
</code></pre></div></div>

<p>Let’s look at the output:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[('sim',), ('imp',), ('mpl',), ('ple',)]
[('sca',), ('cal',), ('ale',), ('lea',), ('eab',), ('abl',), ('ble',)]
[('pre',), ('rep',), ('epr',), ('pro',), ('roc',), ('oce',), ('ces',), ('ess',), ('ssi',), ('sin',), ('ing',)]
[('pyt',), ('yto',), ('tor',), ('orc',), ('rch',)]
</code></pre></div></div>

<p>Hmm… Something looks weird, each string is embedded in a tuple. The issue is
PyTorch uses a collation function which is designed for their <code class="language-plaintext highlighter-rouge">Tensor</code> type. It
doesn’t work great in this case. Luckily, we can define our own to fix this! In
the following code I will use <code class="language-plaintext highlighter-rouge">...</code> to represent code shown above. First, we
need to figure out what the input to <code class="language-plaintext highlighter-rouge">collate_fn</code> even looks like. Add the
<code class="language-plaintext highlighter-rouge">collate_fn</code> to <code class="language-plaintext highlighter-rouge">WordSplitter</code></p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">class</span> <span class="nc">WordSplitter</span><span class="p">(</span><span class="n">Dataset</span><span class="p">):</span>
 	<span class="p">...</span>
    
    <span class="o">@</span><span class="nb">classmethod</span>
    <span class="k">def</span> <span class="nf">collate_fn</span><span class="p">(</span><span class="o">*</span><span class="n">batch</span><span class="p">):</span>
        <span class="k">print</span><span class="p">(</span><span class="sa">f</span><span class="s">"BATCH: </span><span class="si">{</span><span class="n">batch</span><span class="si">}</span><span class="s">"</span><span class="p">)</span>
        <span class="k">return</span> <span class="p">[]</span>
</code></pre></div></div>

<p>The <code class="language-plaintext highlighter-rouge">@classmethod</code> decorator allows us to call <code class="language-plaintext highlighter-rouge">WordSplitter.collate_fn</code>
(you’ll see it in a moment). I use <code class="language-plaintext highlighter-rouge">*batch</code> to tuple up all of the inputs if
the arity is greater than one. The <code class="language-plaintext highlighter-rouge">collate_fn</code> isn’t complete but this allows
us to inspect our inputs to the function. Second, we add our new function to
the <code class="language-plaintext highlighter-rouge">DataLoader</code>:</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">loader</span> <span class="o">=</span> <span class="n">DataLoader</span><span class="p">(</span>
	<span class="p">...,</span>
    <span class="n">collate_fn</span><span class="o">=</span><span class="n">WordSplitter</span><span class="p">.</span><span class="n">collate_fn</span><span class="p">,</span>
<span class="p">)</span>
</code></pre></div></div>

<p>Note, you don’t want to run this test over your entire data set. I would
suggest doing this on a small subset of inputs. If we loop over the loader
again,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BATCH: (&lt;class '__main__.WordSplitter'&gt;, [['sim', 'imp', 'mpl', 'ple']])
BATCH: (&lt;class '__main__.WordSplitter'&gt;, [['sca', 'cal', 'ale', 'lea', 'eab', 'abl', 'ble']])
BATCH: (&lt;class '__main__.WordSplitter'&gt;, [['pre', 'rep', 'epr', 'pro', 'roc', 'oce', 'ces', 'ess', 'ssi', 'sin', 'ing']])
BATCH: (&lt;class '__main__.WordSplitter'&gt;, [['pyt', 'yto', 'tor', 'orc', 'rch']])
[]
[]
[]
[]
</code></pre></div></div>

<p>Let’s modify <code class="language-plaintext highlighter-rouge">batch_size=2</code> in the <code class="language-plaintext highlighter-rouge">loader</code> and see what happens when there is actual batching,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BATCH: (&lt;class '__main__.WordSplitter'&gt;, [['sim', 'imp', 'mpl', 'ple'], ['sca', 'cal', 'ale', 'lea', 'eab', 'abl', 'ble']])
BATCH: (&lt;class '__main__.WordSplitter'&gt;, [['pre', 'rep', 'epr', 'pro', 'roc', 'oce', 'ces', 'ess', 'ssi', 'sin', 'ing'], ['pyt', 'yto', 'tor', 'orc', 'rch']])
[]
[]
</code></pre></div></div>

<p>Okay, so PyTorch returns something like <code class="language-plaintext highlighter-rouge">(DatasetObject, [metadata0, metadata1,
...])</code>. All we need to do is extract the list of metadata from the tuple and
return it, i.e.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="nb">classmethod</span>
<span class="k">def</span> <span class="nf">collate_fn</span><span class="p">(</span><span class="o">*</span><span class="n">batch</span><span class="p">):</span>
    <span class="k">return</span> <span class="n">batch</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
</code></pre></div></div>

<p>In the <code class="language-plaintext highlighter-rouge">for</code> loop we need to additionally loop over the returned list of metadata, i.e.</p>

<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="n">metadatas</span> <span class="ow">in</span> <span class="n">loader</span><span class="p">:</span>
    <span class="k">for</span> <span class="n">metadata</span> <span class="ow">in</span> <span class="n">metadatas</span><span class="p">:</span>
        <span class="k">print</span><span class="p">(</span><span class="n">metadata</span><span class="p">)</span>
</code></pre></div></div>

<p>Result with <code class="language-plaintext highlighter-rouge">batch_size=1</code>,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>['sim', 'imp', 'mpl', 'ple']
['sca', 'cal', 'ale', 'lea', 'eab', 'abl', 'ble']
['pre', 'rep', 'epr', 'pro', 'roc', 'oce', 'ces', 'ess', 'ssi', 'sin', 'ing']
['pyt', 'yto', 'tor', 'orc', 'rch']
</code></pre></div></div>

<p>With <code class="language-plaintext highlighter-rouge">batch_size=2</code>,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>['sim', 'imp', 'mpl', 'ple']
['sca', 'cal', 'ale', 'lea', 'eab', 'abl', 'ble']
['pre', 'rep', 'epr', 'pro', 'roc', 'oce', 'ces', 'ess', 'ssi', 'sin', 'ing']
['pyt', 'yto', 'tor', 'orc', 'rch']
</code></pre></div></div>

<p>With <code class="language-plaintext highlighter-rouge">batch_size=4</code>,</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>['sim', 'imp', 'mpl', 'ple']
['sca', 'cal', 'ale', 'lea', 'eab', 'abl', 'ble']
['pre', 'rep', 'epr', 'pro', 'roc', 'oce', 'ces', 'ess', 'ssi', 'sin', 'ing']
['pyt', 'yto', 'tor', 'orc', 'rch']
</code></pre></div></div>

<p>Heck yes, this is exactly what we want! You could easily write this metadata
somewhere for further use. The key thing to remember here is that the
parallelism happens over batches, in this case the maximum possible cores used
with varying batch sizes:</p>

<table>
  <thead>
    <tr>
      <th><code class="language-plaintext highlighter-rouge">batch_size</code></th>
      <th>cores</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>4</td>
    </tr>
    <tr>
      <td>2</td>
      <td>2</td>
    </tr>
    <tr>
      <td>4</td>
      <td>1</td>
    </tr>
  </tbody>
</table>

<p>The full code is available in a Jupyter Notebook on
<a href="https://github.com/chiroptical/pytorch-ray-workflow">Github</a>. This concludes
part 0. Next time we’ll look into Ray and let it coordinate the
<code class="language-plaintext highlighter-rouge">Dataset/DataLoader</code> workflow over multiple nodes!</p>

<p>If you have any suggestions or improvements please message me on BlueSky
<a href="https://bsky.app/profile/chiroptical.dev">@chiroptical.dev</a> or submit an issue on
<a href="https://github.com/chiroptical/pytorch-ray-workflow">Github</a>.</p>

<h5 id="edits">Edits</h5>

<ul>
  <li>05/20/2020: Use snake-case over camel-case for <code class="language-plaintext highlighter-rouge">wordSplitter</code></li>
</ul>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Simple Scaleable Preprocessing With Pytorch and Ray]]></summary></entry><entry><title type="html">Path to Beginnery in Functional Programming with Haskell - 1</title><link href="https://chiroptical.github.io/posts/2018-10-18-path-to-beginnery-in-functional-programming-with-haskell.html" rel="alternate" type="text/html" title="Path to Beginnery in Functional Programming with Haskell - 1" /><published>2018-10-18T00:00:00+00:00</published><updated>2018-10-18T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/path-to-beginnery-in-functional-programming-with-haskell</id><content type="html" xml:base="https://chiroptical.github.io/posts/2018-10-18-path-to-beginnery-in-functional-programming-with-haskell.html"><![CDATA[<h2 id="path-to-beginnery-in-functional-programming-with-haskell">Path To Beginnery in Functional Programming with Haskell</h2>

<p>See <a href="/blog/path-to-beginnery-in-functional-programming-with-haskell">the first post in this
series</a> for an
introduction to this series. Quick recap: I am trying to track my path
completing Haskell programming projects from books I am reading. Feel free to
message me on BlueSky <a href="https://bsky.app/profile/chiroptical.dev">@chiroptical.dev</a> with any
corrections or suggestions on new topics.</p>

<h2 id="project-1">Project 1</h2>

<p>This is a short problem, but I was getting stuck on a <code class="language-plaintext highlighter-rouge">foldr</code> implementation.
I wanted to write down the problem, reductions, correct solution, and some
alternate implementations to increase my understanding.</p>

<h4 id="definition-of-problem">Definition of Problem</h4>

<p>Implement <code class="language-plaintext highlighter-rouge">myMaximumBy</code> using a fold. <code class="language-plaintext highlighter-rouge">myMaximumBy</code> takes a comparison
function, of type <code class="language-plaintext highlighter-rouge">(a -&gt; a -&gt; Ordering)</code>, and returns the greatest element of
the list based on the last value in the list which returned <code class="language-plaintext highlighter-rouge">GT</code>. Some
examples:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">Prelude</span><span class="o">&gt;</span> <span class="n">myMaximumBy</span> <span class="p">(</span><span class="nf">\</span><span class="kr">_</span> <span class="kr">_</span> <span class="o">-&gt;</span> <span class="kt">GT</span><span class="p">)</span> <span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">]</span>
<span class="mi">1</span>
<span class="kt">Prelude</span><span class="o">&gt;</span> <span class="n">myMaximumBy</span> <span class="p">(</span><span class="nf">\</span><span class="kr">_</span> <span class="kr">_</span> <span class="o">-&gt;</span> <span class="kt">LT</span><span class="p">)</span> <span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">]</span>
<span class="mi">10</span>
<span class="kt">Prelude</span><span class="o">&gt;</span> <span class="n">myMaximumBy</span> <span class="n">compare</span> <span class="p">[</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">]</span>
<span class="mi">10</span>
</code></pre></div></div>

<h4 id="solving-the-problem">Solving The Problem</h4>

<p>The base case, or accumulator, is simply the first value in the list. My
initial thought is that given an empty list our function should return an
error. Side note: after additional thought I decided to implement a version which
returns <code class="language-plaintext highlighter-rouge">Maybe a</code>, but I will show that in the <strong>Practical Considerations</strong>
section. If given a list with one element, simply return that element. Next we
need to define our folding function (for a <code class="language-plaintext highlighter-rouge">foldr</code>),</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">folder</span> <span class="o">::</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span>
<span class="n">folder</span> <span class="n">f</span> <span class="n">x</span> <span class="n">acc</span> <span class="o">=</span> <span class="kr">if</span> <span class="n">f</span> <span class="n">x</span> <span class="n">acc</span> <span class="o">==</span> <span class="kt">GT</span> <span class="kr">then</span> <span class="n">x</span> <span class="kr">else</span> <span class="n">acc</span>
</code></pre></div></div>

<p>and the full <code class="language-plaintext highlighter-rouge">foldr</code> with pattern matches for empty and single-item lists,</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">myMaximumBy</span> <span class="o">::</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="n">a</span>
<span class="n">myMaximumBy</span> <span class="kr">_</span> <span class="kt">[]</span> <span class="o">=</span> <span class="n">error</span> <span class="s">"Cannot myMaximumBy on empty list!"</span>
<span class="n">myMaximumBy</span> <span class="kr">_</span> <span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span>
<span class="n">myMaximumBy</span> <span class="n">f</span> <span class="n">xs</span> <span class="o">=</span> <span class="n">foldr</span> <span class="p">(</span><span class="n">folder</span> <span class="n">f</span><span class="p">)</span> <span class="p">(</span><span class="n">head</span> <span class="n">xs</span><span class="p">)</span> <span class="o">$</span> <span class="n">tail</span> <span class="n">xs</span>
</code></pre></div></div>

<p>For a novice, this might look like working code as it will type check! However,
it doesn’t work correctly. A <code class="language-plaintext highlighter-rouge">foldr</code> breaks down like this for <code class="language-plaintext highlighter-rouge">[a]</code> with 3 items:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">foldr</span> <span class="n">g</span> <span class="n">acc</span> <span class="p">[</span><span class="n">a</span><span class="p">,</span> <span class="n">a'</span><span class="p">,</span> <span class="n">a''</span><span class="p">]</span>
<span class="c1">-- ==</span>
<span class="c1">-- g a (g a' (g a'' acc))</span>
</code></pre></div></div>

<p>Let’s take the example where,</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">-- Omitting types</span>
<span class="n">g</span> <span class="o">=</span> <span class="n">folder</span> <span class="n">f</span>
<span class="n">f</span> <span class="o">=</span> <span class="nf">\</span><span class="kr">_</span> <span class="kr">_</span> <span class="o">-&gt;</span> <span class="kt">GT</span>

<span class="c1">-- Reduction (g x x' = x, always!)</span>
<span class="c1">-- 1. g a (g a' a'')</span>
<span class="c1">-- 2. g a a'</span>
<span class="c1">-- 3. a</span>
</code></pre></div></div>

<p>Which is not what we are looking for! We actually want to return <code class="language-plaintext highlighter-rouge">a''</code>. To
do that, we need <code class="language-plaintext highlighter-rouge">foldl</code>,</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">folder</span> <span class="o">::</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span>
<span class="n">folder</span> <span class="n">f</span> <span class="n">acc</span> <span class="n">x</span> <span class="o">=</span> <span class="kr">if</span> <span class="n">f</span> <span class="n">acc</span> <span class="n">x</span> <span class="o">==</span> <span class="kt">GT</span> <span class="kr">then</span> <span class="n">acc</span> <span class="kr">else</span> <span class="n">x</span>

<span class="n">myMaximumBy</span> <span class="o">::</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="n">a</span>
<span class="n">myMaximumBy</span> <span class="kr">_</span> <span class="kt">[]</span> <span class="o">=</span> <span class="n">error</span> <span class="s">"Cannot myMaximumBy on empty list!"</span>
<span class="n">myMaximumBy</span> <span class="kr">_</span> <span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">=</span> <span class="n">x</span>
<span class="n">myMaximumBy</span> <span class="n">f</span> <span class="n">xs</span> <span class="o">=</span> <span class="n">foldl</span> <span class="p">(</span><span class="n">folder</span> <span class="n">f</span><span class="p">)</span> <span class="p">(</span><span class="n">head</span> <span class="n">xs</span><span class="p">)</span> <span class="o">$</span> <span class="n">tail</span> <span class="n">xs</span>

<span class="c1">-- Reduction</span>
<span class="c1">-- 1. f (f a a') a''</span>
<span class="c1">-- 2. f a' a''</span>
<span class="c1">-- 3. a''</span>
</code></pre></div></div>

<h2 id="practical-considerations">Practical Considerations</h2>

<h4 id="implement----maybe-a-version">Implement <code class="language-plaintext highlighter-rouge">... -&gt; Maybe a</code> Version</h4>

<p>Let’s remove the version of <code class="language-plaintext highlighter-rouge">myMaximumBy</code> which errors out by returning
<code class="language-plaintext highlighter-rouge">Nothing</code> when given an empty list and a <code class="language-plaintext highlighter-rouge">Maybe a</code> otherwise.</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">folder</span> <span class="o">::</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span>
<span class="n">folder</span> <span class="n">f</span> <span class="p">(</span><span class="kt">Just</span> <span class="n">acc</span><span class="p">)</span> <span class="n">x</span> <span class="o">=</span> <span class="kr">if</span> <span class="n">f</span> <span class="n">acc</span> <span class="n">x</span> <span class="o">==</span> <span class="kt">GT</span> <span class="kr">then</span> <span class="p">(</span><span class="kt">Just</span> <span class="n">acc</span><span class="p">)</span> <span class="kr">else</span> <span class="p">(</span><span class="kt">Just</span> <span class="n">x</span><span class="p">)</span>
<span class="n">folder</span> <span class="kr">_</span> <span class="kr">_</span> <span class="kr">_</span> <span class="o">=</span> <span class="kt">Nothing</span>

<span class="n">myMaximumBy</span> <span class="o">::</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span>
<span class="n">myMaximumBy</span> <span class="kr">_</span> <span class="kt">[]</span> <span class="o">=</span> <span class="kt">Nothing</span>
<span class="n">myMaximumBy</span> <span class="kr">_</span> <span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">=</span> <span class="kt">Just</span> <span class="n">x</span>
<span class="n">myMaximumBy</span> <span class="n">f</span> <span class="n">xs</span> <span class="o">=</span> <span class="n">foldl</span> <span class="p">(</span><span class="n">folder</span> <span class="n">f</span><span class="p">)</span> <span class="p">(</span><span class="kt">Just</span> <span class="o">$</span> <span class="n">head</span> <span class="n">xs</span><span class="p">)</span> <span class="o">$</span> <span class="n">tail</span> <span class="n">xs</span>
</code></pre></div></div>

<p>I don’t think <code class="language-plaintext highlighter-rouge">folder f _ x</code> pattern in necessary, but it definitely doesn’t
hurt.</p>

<h4 id="implement-myminimumby">Implement <code class="language-plaintext highlighter-rouge">myMinimumBy</code></h4>

<p>For <code class="language-plaintext highlighter-rouge">myMinimumBy</code> you simply replace <code class="language-plaintext highlighter-rouge">GT</code> in <code class="language-plaintext highlighter-rouge">folder</code> with <code class="language-plaintext highlighter-rouge">LT</code>. With a little
abstraction, you can write both in a nice point-free style.</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">folder</span> <span class="o">::</span> <span class="kt">Ordering</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span>
<span class="n">folder</span> <span class="n">o</span> <span class="n">f</span> <span class="p">(</span><span class="kt">Just</span> <span class="n">acc</span><span class="p">)</span> <span class="n">x</span> <span class="o">=</span> <span class="kr">if</span> <span class="n">f</span> <span class="n">acc</span> <span class="n">x</span> <span class="o">==</span> <span class="n">o</span> <span class="kr">then</span> <span class="p">(</span><span class="kt">Just</span> <span class="n">acc</span><span class="p">)</span> <span class="kr">else</span> <span class="p">(</span><span class="kt">Just</span> <span class="n">x</span><span class="p">)</span>
<span class="n">folder</span> <span class="kr">_</span> <span class="kr">_</span> <span class="kr">_</span> <span class="kr">_</span> <span class="o">=</span> <span class="kt">Nothing</span>

<span class="n">myOrderingBy</span> <span class="o">::</span> <span class="kt">Ordering</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span>
<span class="n">myOrderingBy</span> <span class="kr">_</span> <span class="kr">_</span> <span class="kt">[]</span> <span class="o">=</span> <span class="kt">Nothing</span>
<span class="n">myOrderingBy</span> <span class="kr">_</span> <span class="kr">_</span> <span class="p">[</span><span class="n">x</span><span class="p">]</span> <span class="o">=</span> <span class="kt">Just</span> <span class="n">x</span>
<span class="n">myOrderingBy</span> <span class="n">o</span> <span class="n">f</span> <span class="n">as</span> <span class="o">=</span> <span class="n">foldl</span> <span class="p">(</span><span class="n">folder</span> <span class="n">o</span> <span class="n">f</span><span class="p">)</span> <span class="p">(</span><span class="kt">Just</span> <span class="o">$</span> <span class="n">head</span> <span class="n">as</span><span class="p">)</span> <span class="o">$</span> <span class="n">tail</span> <span class="n">as</span>

<span class="n">myMaximumBy</span> <span class="o">::</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span>
<span class="n">myMaximumBy</span> <span class="o">=</span> <span class="n">myOrderingBy</span> <span class="kt">GT</span>

<span class="n">myMinimumBy</span> <span class="o">::</span> <span class="p">(</span><span class="n">a</span> <span class="o">-&gt;</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Ordering</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="p">[</span><span class="n">a</span><span class="p">]</span> <span class="o">-&gt;</span> <span class="kt">Maybe</span> <span class="n">a</span>
<span class="n">myMinimumBy</span> <span class="o">=</span> <span class="n">myOrderingBy</span> <span class="kt">LT</span>
</code></pre></div></div>

<h2 id="wrapping-up">Wrapping Up</h2>

<p>This wasn’t a particularly difficult problem or solution, but it was one of the
first cases where my code looked correct, type-checked, and failed. It is
really important to understand the difference between <code class="language-plaintext highlighter-rouge">foldr</code> and <code class="language-plaintext highlighter-rouge">foldl</code>. I am
starting to really enjoy point-free style in Haskell. When understood, it is
terse and beautiful.</p>

<p>Edits made on 10/18/18 cleaning up patterns with unneccesary named parameters.
Replace <code class="language-plaintext highlighter-rouge">(x:[])</code> with <code class="language-plaintext highlighter-rouge">[x]</code>.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Path To Beginnery in Functional Programming with Haskell]]></summary></entry><entry><title type="html">C++ Recursive Template Metaprogramming: Fibonacci Numbers</title><link href="https://chiroptical.github.io/posts/2018-07-01-c-recursive-template-metaprogramming-fibonacci-numbers.html" rel="alternate" type="text/html" title="C++ Recursive Template Metaprogramming: Fibonacci Numbers" /><published>2018-07-01T00:00:00+00:00</published><updated>2018-07-01T00:00:00+00:00</updated><id>https://chiroptical.github.io/posts/c-recursive-template-metaprogramming-fibonacci-numbers</id><content type="html" xml:base="https://chiroptical.github.io/posts/2018-07-01-c-recursive-template-metaprogramming-fibonacci-numbers.html"><![CDATA[<h2 id="background">Background</h2>

<p>After a brief dive into Scala, I am back to writing C++. However, I do have a
much better appreciation for functional programming and recursion. I am far
from an expert at either, but I am interested in increasing my programming
skills. I decided to revive my blog and try to post things I find fun or
interesting. I am currently reading “Effective Modern C++” by Scott Meyers and
continually come across Metaprogramming online. I was poking around Stack
Overflow and I found <a href="https://stackoverflow.com/questions/22449902/tail-recursion-performance-on-template-meta-programming">this
post</a>
which asks about tail recursion in Template Metaprogramming (TMP). I thought
this was interesting and decided to see if I could write the naive recursive
Fibonacci number generator using TMP.</p>

<p>I had already written this in Scala, which looks like:</p>

<div class="language-scala highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">import</span> <span class="nn">scala.annotation.tailrec</span>
<span class="k">def</span> <span class="nf">fib</span><span class="o">(</span><span class="n">n</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)</span><span class="k">:</span> <span class="kt">Int</span> <span class="o">=</span> <span class="o">{</span>
    <span class="nd">@tailrec</span>
    <span class="k">def</span> <span class="nf">loop</span><span class="o">(</span><span class="n">iter</span><span class="k">:</span> <span class="kt">Int</span><span class="o">,</span> <span class="n">prev</span><span class="k">:</span> <span class="kt">Int</span><span class="o">,</span> <span class="n">next</span><span class="k">:</span> <span class="kt">Int</span><span class="o">)</span><span class="k">:</span> <span class="kt">Int</span> <span class="o">=</span> <span class="o">{</span>
        <span class="nf">if</span> <span class="o">(</span><span class="n">iter</span> <span class="o">&gt;=</span> <span class="n">n</span><span class="o">)</span> <span class="n">prev</span>
        <span class="k">else</span> <span class="nf">loop</span><span class="o">(</span><span class="n">iter</span> <span class="o">+</span> <span class="mi">1</span><span class="o">,</span> <span class="n">next</span><span class="o">,</span> <span class="n">prev</span> <span class="o">+</span> <span class="n">next</span><span class="o">)</span>
    <span class="o">}</span>
    <span class="nf">loop</span><span class="o">(</span><span class="mi">0</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">1</span><span class="o">)</span>
<span class="o">}</span>
<span class="nf">fib</span><span class="o">(</span><span class="mi">10</span><span class="o">)</span>
</code></pre></div></div>

<p>However, <code class="language-plaintext highlighter-rouge">fib(10)</code> will execute at runtime and the Java Virtual Machine occurs
additional runtime overhead each time you run the program. A neat benefit of
TMP in C++ is the compiler can compute <code class="language-plaintext highlighter-rouge">fib(10)</code> and then each invocation of
the program is as simple as printing an integer. My first implementation in
C++, looked like:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;cstdint&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="k">namespace</span> <span class="n">impl</span> <span class="p">{</span>

    <span class="k">template</span><span class="o">&lt;</span><span class="kt">int64_t</span> <span class="n">n</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">isPositive</span><span class="p">&gt;</span>
    <span class="k">struct</span> <span class="nc">fib_impl</span> <span class="p">{</span>
        <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="n">fib_impl</span><span class="o">&lt;</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">isPositive</span><span class="o">&gt;::</span><span class="n">val</span> <span class="o">+</span> <span class="n">fib_impl</span><span class="o">&lt;</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="n">isPositive</span><span class="o">&gt;::</span><span class="n">val</span><span class="p">;</span>
    <span class="p">};</span>

    <span class="k">template</span><span class="o">&lt;</span><span class="p">&gt;</span>
    <span class="k">struct</span> <span class="nc">fib_impl</span><span class="o">&lt;</span><span class="mi">1</span><span class="p">,</span> <span class="nb">true</span><span class="o">&gt;</span> <span class="p">{</span>
        <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
    <span class="p">};</span>

    <span class="k">template</span><span class="o">&lt;</span><span class="p">&gt;</span>
    <span class="k">struct</span> <span class="nc">fib_impl</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">,</span> <span class="nb">true</span><span class="o">&gt;</span> <span class="p">{</span>
        <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
    <span class="p">};</span>

    <span class="c1">// If calling fib&lt;-1&gt;::val it will try to do the recursion infinitely</span>
    <span class="c1">// -&gt; this template short circuits that recursion</span>
    <span class="k">template</span><span class="o">&lt;</span><span class="kt">int64_t</span> <span class="n">n</span><span class="p">&gt;</span>
    <span class="k">struct</span> <span class="nc">fib_impl</span><span class="o">&lt;</span><span class="n">n</span><span class="p">,</span> <span class="nb">false</span><span class="o">&gt;</span> <span class="p">{</span>
        <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
    <span class="p">};</span>

<span class="p">}</span> <span class="c1">// namespace impl</span>

<span class="k">template</span><span class="o">&lt;</span><span class="kt">int64_t</span> <span class="n">n</span><span class="p">&gt;</span>
<span class="k">struct</span> <span class="nc">fib</span> <span class="p">{</span>
    <span class="k">static_assert</span><span class="p">(</span><span class="n">n</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">,</span> <span class="s">"Error: fib can't be called with a negative integer"</span><span class="p">);</span>
    <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="n">impl</span><span class="o">::</span><span class="n">fib_impl</span><span class="o">&lt;</span><span class="n">n</span><span class="p">,</span> <span class="p">(</span><span class="n">n</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span><span class="o">&gt;::</span><span class="n">val</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">//    static_assert(fib&lt;-1&gt;::val); // This will fail.</span>
<span class="c1">//    static_assert(fib&lt;10&gt;::val == 55); // Make sure it works at compile time!</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">fib</span><span class="o">&lt;</span><span class="mi">91</span><span class="o">&gt;::</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>I want the interface of <code class="language-plaintext highlighter-rouge">fib</code> to accept only a positive integer, therefore we
abstract away whether, or not, the integer is positive with <code class="language-plaintext highlighter-rouge">impl::fib_impl</code>.
In this implementation, you need 3 template specializations. Two are the
termination conditions: 0 and 1; the other provides protection from an infinite
recursion when you give a negative number to <code class="language-plaintext highlighter-rouge">fib</code>. Even though you get an
error from the <code class="language-plaintext highlighter-rouge">static_assert(fib&lt;-1&gt;::val)</code>, the compiler still tries to
create infinite templates. Luckily, your compiler will protect you from
creating literally infinite templates (GCC 7.2.1 allowed 900 to be generated,
use <code class="language-plaintext highlighter-rouge">-ftemplate-depth=&lt;value&gt;</code> to change it). This implementation isn’t tail
recursive because the recursion isn’t in the tail position. The recursive call,</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fib_impl</span><span class="o">&lt;</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">isPositive</span><span class="o">&gt;::</span><span class="n">val</span> <span class="o">+</span> <span class="n">fib_impl</span><span class="o">&lt;</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">,</span> <span class="n">isPositive</span><span class="o">&gt;::</span><span class="n">val</span>
</code></pre></div></div>

<p>is shaped like <code class="language-plaintext highlighter-rouge">recursive_template(...) + recursive_template(...)</code>, but must
look like: <code class="language-plaintext highlighter-rouge">recursive_template(...)</code> to be tail recursive. You can verify this
by modifying the Scala code. In C++, I believe the only way to find out if tail
recursion is actually applied is looking at the assembly for loops.
Unfortunately, this is done at compile time and you can’t review the compile
time assembly (to my knowledge). The tail recursive implementation is:</p>

<div class="language-cpp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp">#include</span> <span class="cpf">&lt;cstdint&gt;</span><span class="cp">
#include</span> <span class="cpf">&lt;iostream&gt;</span><span class="cp">
</span>
<span class="k">namespace</span> <span class="n">impl</span> <span class="p">{</span>

    <span class="k">template</span> <span class="o">&lt;</span><span class="kt">int64_t</span> <span class="n">n</span><span class="p">,</span> <span class="kt">int64_t</span> <span class="n">prev</span><span class="p">,</span> <span class="kt">int64_t</span> <span class="n">next</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">isPositive</span><span class="p">&gt;</span>
    <span class="k">struct</span> <span class="nc">fib_impl</span> <span class="p">{</span>
        <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="n">fib_impl</span><span class="o">&lt;</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">next</span><span class="p">,</span> <span class="n">prev</span> <span class="o">+</span> <span class="n">next</span><span class="p">,</span> <span class="n">isPositive</span><span class="o">&gt;::</span><span class="n">val</span><span class="p">;</span>
    <span class="p">};</span>

    <span class="k">template</span> <span class="o">&lt;</span><span class="kt">int64_t</span> <span class="n">prev</span><span class="p">,</span> <span class="kt">int64_t</span> <span class="n">next</span><span class="p">&gt;</span>
    <span class="k">struct</span> <span class="nc">fib_impl</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">,</span> <span class="n">prev</span><span class="p">,</span> <span class="n">next</span><span class="p">,</span> <span class="nb">true</span><span class="o">&gt;</span> <span class="p">{</span>
        <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="n">prev</span><span class="p">;</span>
    <span class="p">};</span>

    <span class="k">template</span> <span class="o">&lt;</span><span class="kt">int64_t</span> <span class="n">n</span><span class="p">,</span> <span class="kt">int64_t</span> <span class="n">prev</span><span class="p">,</span> <span class="kt">int64_t</span> <span class="n">next</span><span class="p">&gt;</span>
    <span class="k">struct</span> <span class="nc">fib_impl</span><span class="o">&lt;</span><span class="n">n</span><span class="p">,</span> <span class="n">prev</span><span class="p">,</span> <span class="n">next</span><span class="p">,</span> <span class="nb">false</span><span class="o">&gt;</span> <span class="p">{</span>
        <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
    <span class="p">};</span>

<span class="p">}</span> <span class="c1">// namespace impl</span>


<span class="k">template</span> <span class="o">&lt;</span><span class="kt">int64_t</span> <span class="n">n</span><span class="p">&gt;</span>
<span class="k">struct</span> <span class="nc">fib</span> <span class="p">{</span>
    <span class="k">static_assert</span><span class="p">(</span><span class="n">n</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">,</span> <span class="s">"Error: fib can't be called with negative numbers!"</span><span class="p">);</span>
    <span class="k">static</span> <span class="k">constexpr</span> <span class="kt">int64_t</span> <span class="n">val</span> <span class="o">=</span> <span class="n">impl</span><span class="o">::</span><span class="n">fib_impl</span><span class="o">&lt;</span><span class="n">n</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="n">n</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">)</span><span class="o">&gt;::</span><span class="n">val</span><span class="p">;</span>
<span class="p">};</span>

<span class="kt">int</span> <span class="n">main</span><span class="p">()</span> <span class="p">{</span>
<span class="c1">//    static_assert(fib&lt;-1&gt;::val); // This will fail.</span>
<span class="c1">//    static_assert(fib&lt;10&gt;::val == 55); // Make sure it works at compile time</span>
    <span class="n">std</span><span class="o">::</span><span class="n">cout</span> <span class="o">&lt;&lt;</span> <span class="n">fib</span><span class="o">&lt;</span><span class="mi">91</span><span class="o">&gt;::</span><span class="n">val</span> <span class="o">&lt;&lt;</span> <span class="sc">'\n'</span><span class="p">;</span>
    <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Great, now the recursive call is in the tail position. Additionally, we only
need 2 template specializations. The one where <code class="language-plaintext highlighter-rouge">n = 0</code> and the infinite
template recursion protection for negative integers. I compiled both versions
with GCC 7.2.1 using the C++11 standard (which is necessary for <code class="language-plaintext highlighter-rouge">constexpr</code>) 10
times and measured the average compile time. It was essentially the same (about
0.2s). The tail recursive version has a major downside though: it overflows a
<code class="language-plaintext highlighter-rouge">int64_t</code> faster than the non-tail recursive version. The largest value of <code class="language-plaintext highlighter-rouge">n</code>
for the non-tail recursive version was 92 and for the tail recursive version
was 91. The reason for this is because the template recursion for
<code class="language-plaintext highlighter-rouge">fib&lt;92&gt;::val</code> contains a <code class="language-plaintext highlighter-rouge">prev + next</code> which would contain a value to large to
fit in <code class="language-plaintext highlighter-rouge">int64_t</code>.</p>

<p>This code was an academic exercise, but I think it is neat. This is my first
experience with TMP and I am very interested to learn more. Feel free to
message me, or follow me, on <a href="https://bsky.app/profile/chiroptical.dev">BlueSky</a> with constructive criticism or for future
blog posts.</p>]]></content><author><name></name></author><category term="jekyll" /><category term="blog" /><summary type="html"><![CDATA[Background]]></summary></entry></feed>