<?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="http://arialdomartini.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="http://arialdomartini.github.io/" rel="alternate" type="text/html" /><updated>2026-03-07T09:58:10+00:00</updated><id>http://arialdomartini.github.io/feed.xml</id><title type="html">Arialdo on Code</title><subtitle>Random thoughts about programming</subtitle><author><name>Arialdo Martini</name></author><entry><title type="html">Pre-emptive Commit Messages</title><link href="http://arialdomartini.github.io/pre-emptive-commit-comments" rel="alternate" type="text/html" title="Pre-emptive Commit Messages" /><published>2026-02-20T00:00:00+00:00</published><updated>2026-02-20T00:00:00+00:00</updated><id>http://arialdomartini.github.io/pre-emptive-commit-comments</id><content type="html" xml:base="http://arialdomartini.github.io/pre-emptive-commit-comments"><![CDATA[<ol>
  <li>Write commit messages before coding.</li>
  <li>Describe how the software behaves, not what you have done.</li>
</ol>

<!--more-->

<h2 id="behaviours-not-tests">Behaviours, Not Tests</h2>

<p>Daniel Terhorst-North changed my life.</p>

<p>I always recommend his <a href="https://dannorth.net/blog/introducing-bdd/">Introducing
BDD</a>. It explains how
Behaviour-Driven Development started from the intuition that TDD is
not merely about testing. The word “<em>test</em>” itself points developers
in the wrong direction, he says, toward verification, toward the
past. He prefers using “<em>behaviour</em>”.</p>

<p>It’s a dramatic change of perspective. For Daniel tests document the
system’s behaviour from the outside, from the point of view of its
clients or users; therefore, they describe what the system <em>should
do</em>, using narrative sentences.</p>

<p>They are in fact business requirements, written in the business
language and, of course, conceived before the implementation even
exists.</p>

<h2 id="why-test-first">Why Test-First?</h2>

<p>Some find it counterintuitive, if not crazy, writing tests before the
system under test even exists. Yet, if you replace the word “test”
with “requirement”, all makes sense, and it’s the opposite approach to
sound crazy. What are we supposed to do? To write the code without
knowing where to go and then, when we are done, to figure out what the
requirements were?</p>

<p>If only TDD was called Requirement-Driven Development, no one would
find it counterintuitive. “<em>Test</em>” suggests the idea of verifying
something that is already done. Not the most fortunate pick, Kent…</p>

<p>As Daniel wrote:</p>

<blockquote>
  <p>A really useful way to stay focused was to ask:<br />
“What’s the next most important thing the system doesn’t do?”</p>
</blockquote>

<p>This question defines your next test; the test becomes a statement of
intent, a promise. With the test in place, you <em>commit</em> (here’s the
word!) to a specific, future behaviour for your product.</p>

<h2 id="a-commit-is-a-promise">A Commit Is A Promise</h2>

<p>I started thinking to commit messages the same way, and
something clicked. Maybe the word “<em>commit</em>” in the Git lingo is not casual.
Maybe making a commit means making a promise too.</p>

<p>It’s ironic how Git lets you <em>commit</em> to something when the code is
already complete. A bit late, indeed. The real twist is how in
<a href="https://docs.jj-vcs.dev/latest/">Jujutsu</a> it’s the exact opposite to be idiomatic: you first
<code class="language-plaintext highlighter-rouge">jj commit</code>, then you write the code.<br />
We’ll get this in few seconds. Back to the message.</p>

<h2 id="how-to-describe-a-promise">How To Describe A Promise?</h2>

<p>A commit message such as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Use Set instead of List
</code></pre></div></div>

<p>is neither a commitment nor a behaviour description: it’s an activity
report.<br />
It makes more sense when written in the style of a BDD method:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The cart does not crash when it contains more than 10k items
</code></pre></div></div>

<p>That’s not a cosmetic difference. The former is about the actions
performed by the programmer, the past, the <em>how</em>. The latter about
the feature, the present, the <em>what</em>.</p>

<h2 id="tell-me-what-the-software-does-not-what-you-have-done">Tell Me What The Software Does, Not What You Have Done</h2>

<p>The second form is what I would like to read in the Git history, and
is in line with the idea of <a href="https://www.conventionalcommits.org">Conventional
Commits</a>, which promise to “<a href="https://www.conventionalcommits.org/en/v1.0.0/#why-use-conventional-commits">Automatically
generate CHANGELOGs</a>”.</p>

<p>When I check out a commit, I know that someone worked hard on their
keyboard to make the software behave like it should. Kudos, I’m
grateful. But when it’s my turn to work on top of that commit there’s
no point answering the question:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>What did the programmers do during that work session?
</code></pre></div></div>

<p>It’s more useful to have an answer to:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>What's the project behaviour NOW?
</code></pre></div></div>

<p>As <a href="https://jesuswasrasta.com/">Ferdinando Santacroce</a> loves to say: the commit message
should capture what cannot be deduced from the code only: the context,
the motivation and the thought process behind the solution. To me,
that alone is a good reason not to let LLMs write my commit messages.</p>

<h2 id="write-it-first">Write It First</h2>
<p>Then I stumbled upon this tweet by <a href="https://twitter.com/erwilleke">Eric Willeke</a>:</p>

<p><img src="static/img/pre-emptive-commit-messages/erik-git-comments1.png" alt="Eric Willeke Tweet" /></p>

<p>A point of view of disarming simplicity. It’s <strong>test-first applied to
version control</strong>. It instantly resonated with me.</p>

<p>If you are accustomed to write tests before the implementation,
writing commit messages before coding will be just as
natural. Messages become statement of intents, commits become
commitments.</p>

<p>This is how the <a href="https://steveklabnik.github.io/jujutsu-tutorial/real-world-workflows/the-squash-workflow.html">Squash
Workflow</a>
works in Jujutsu. It revolves around the idea of creating a new empty
revision, together with its description, even before touching any
file. Not a coincidence that the command to do this is <code class="language-plaintext highlighter-rouge">jj commit</code>. The commit message as the intent and the unit of work.</p>

<p>First you write it, then you make it true.</p>

<h1 id="what-happens-when-you-do-it">What Happens When You Do It</h1>

<p>In 2012, with my teammates we started applying this technique, with
Git. It was a matter of doing</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit --allow-empty -m &lt;message&gt;
</code></pre></div></div>

<p>followed by</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit --amend
</code></pre></div></div>

<p>when we were done. Some Git GUIs makes this easy.</p>

<p>Over the years, this is what I experienced:</p>

<ul>
  <li>
    <p><strong>It aligns pair members</strong>. Whether I am the driver or the
navigator, I must agree with my pair on the message and on the
goal. This stimulates a conversation. The moment we start
programming, we genuinely agree on what we want to achieve.<br />
When I code alone, I have to find an agreement with my own
understading. It’s equally challenging and it equally pays off.</p>
  </li>
  <li>
    <p><strong>It’s easier to focus</strong>: tests and commit message are the coding
session’s center of gravity. When I digress, the promise in the commit message is there to bring me back to the point.<br />
I’m less prone to lose focus.</p>
  </li>
  <li>
    <p><strong>It sets a micro scope</strong>: Before, I used to ask myself: “<em>Should I
stop coding now? How much is enough? Am I done yet?</em>”.<br />
 Checking if I reached the planned goal is just easier.</p>
  </li>
  <li>
    <p><strong>Simpler commit reviews</strong>: I always review my changes before making
them final. Instead of asking “<em>Well well well, let’s find out, what
have I done here? I don’t even remember…</em>” I can ask myself “<em>Have
I done all and only what I committed to?</em>”.<br />
It’s a much easier and targeted question to answer.</p>
  </li>
  <li>
    <p><strong>More accurate and faithful statements</strong>: when writing the message
before coding, being very specific comes naturally. It’s easy to
refrain from being vague and writing <code class="language-plaintext highlighter-rouge">Fix</code> or <code class="language-plaintext highlighter-rouge">Update
Repository.cs</code>. The message and the resulting commit content
naturally match, because the message was the goal since the very
beginning.</p>
  </li>
  <li>
    <p><strong>Each message triggers a micro design session</strong>: the mere act of
defining the commit message requires reaching an agreement with my
pairing partner. We need to concord on the words to describe the
desired behaviour, on the names to give to domain concepts and,
ultimately, on which component owns the behaviour. These are all
design questions, and we cannot write the message until we’ve
addressed them.<br />
Starting a pairing session, there’s nothing nicer than discussing
about design.</p>
  </li>
  <li>
    <p><strong>It creates a natural timebox</strong>: I make my best to commit to
baby-step progresses, from a stable state to the next little
goal. It’s easy to verify if a chance belongs or not to the goal.</p>
  </li>
  <li>
    <p><strong>It goes well with short-lived feature branches</strong>: messages define
micro-goals, and they live in the context of the wider goal defined
by the branch name. Which is also pre-emptive, by design.<br />
These 2 levels of goals help me steering the direction.</p>
  </li>
  <li>
    <p><strong>The commit history gains natural granularity</strong>. Each commit has a
single goal (one could say it respects the Single Responsibility
Principle). A feature branch becomes a readable sequence of
behaviours, each commit a small step in a larger story.<br />
A natural changelog emerges.</p>
  </li>
</ul>

<hr />

<p>This experiment was started in 2012 by Arialdo Martini, Mattia
Piccinetti, Gian Marco Gherardi, Guglielmo Brasile, Francesco
Pichierri, and Giuseppe Mariano. It was initially described in
<a href="https://arialdomartini.wordpress.com/2012/09/03/pre-emptive-commit-comments/">Pre-emptive Commit Comments</a>.<br />
It is described in details in the book <a href="https://www.goodreads.com/book/show/25533645-git-essentials">Git
Essentials</a> by <a href="https://jesuswasrasta.com/">Ferdinando Santacroce</a>.</p>

<h1 id="references">References</h1>

<ul>
  <li><a href="https://docs.jj-vcs.dev/latest/">Jujustu</a></li>
  <li><a href="https://www.conventionalcommits.org">Conventional Commits</a></li>
  <li><a href="https://arialdomartini.wordpress.com/2012/09/03/pre-emptive-commit-comments/">Pre-Emptive Commit Comments</a></li>
  <li><a href="https://jesuswasrasta.com/">Ferdinando Santacroce</a>
    <ul>
      <li><a href="https://www.goodreads.com/book/show/25533645-git-essentials">Git Essentials - Ferdinando Santacroce</a></li>
    </ul>
  </li>
</ul>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="git" /><category term="jujutsu" /><summary type="html"><![CDATA[Write commit messages before coding. Describe how the software behaves, not what you have done.]]></summary></entry><entry><title type="html">Monadic Parser Combinators in F#</title><link href="http://arialdomartini.github.io/monadic-parser-combinators" rel="alternate" type="text/html" title="Monadic Parser Combinators in F#" /><published>2025-04-13T00:00:00+00:00</published><updated>2025-04-13T00:00:00+00:00</updated><id>http://arialdomartini.github.io/monadic-parser-combinators</id><content type="html" xml:base="http://arialdomartini.github.io/monadic-parser-combinators"><![CDATA[<p>You want to invent a new language, and you want to do this in F#,
don’t you? And, of course, you want to base its parser on Monadic
Parser Combinators. You’ve always wanted, just admit it.</p>

<!--more-->

<p>The compiler of your beautiful new language — with which you
want to bring the use of <code class="language-plaintext highlighter-rouge">goto</code> and <code class="language-plaintext highlighter-rouge">null</code> back to life — will
have several components:</p>

<ul>
  <li>A Lexer, for splitting the source code into tokens.</li>
  <li>A Parser, to analyze the token sequence and to convert it into a
syntax tree, and to check the grammatical structure.</li>
  <li>An Intermediate Code Generator.</li>
  <li>A Linker, and so on.</li>
</ul>

<p>Here we are focusing on the very first component: a piece of code able
to analyze the source, to check its syntax against the esotheric
formal grammar you defined, and to generate something very well
structured for the next components to crunch.</p>

<p>It would be a (probably very complex) function with a signature
like:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">SourceCode</span> <span class="p">=</span> <span class="kt">string</span>

<span class="k">type</span> <span class="nc">AbstractSyntaxTree</span> <span class="p">=</span>
<span class="p">|</span> <span class="nc">Goto</span> <span class="k">of</span> <span class="nc">Label</span>
<span class="p">|</span> <span class="nc">VariableDefinition</span> <span class="k">of</span> <span class="o">...</span>
<span class="p">|</span> <span class="o">...</span>

<span class="k">val</span> <span class="n">parser</span> <span class="p">:</span> <span class="nc">SourceCode</span> <span class="p">-&gt;</span> <span class="nc">AbstractSyntaxTree</span>
</code></pre></div></div>

<p>Most likely, you would like the parser to fail and to emit syntax
errors in case there are any. Better return a <code class="language-plaintext highlighter-rouge">Result</code>, then:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">ParserError</span> <span class="p">=</span> <span class="p">{</span> <span class="nc">Expected</span><span class="p">:</span> <span class="kt">string</span><span class="p">;</span> <span class="nc">Encountered</span><span class="p">:</span> <span class="kt">string</span> <span class="p">}</span>
<span class="c1">// or just: type ParserError = string</span>

<span class="k">val</span> <span class="n">parser</span> <span class="p">:</span> <span class="nc">SourceCode</span> <span class="p">-&gt;</span> <span class="nc">Result</span><span class="p">&lt;</span><span class="nc">ParserError</span><span class="p">,</span> <span class="nc">AbstractSyntaxTree</span><span class="p">&gt;</span>
</code></pre></div></div>

<p>If you think about it, that’s not qualitatively different from
deserializing a JSON string:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">JSON</span> <span class="p">=</span> <span class="kt">string</span>
<span class="k">type</span> <span class="nc">Error</span> <span class="p">=</span> <span class="kt">string</span>

<span class="k">val</span> <span class="n">jsonDeserializer</span> <span class="p">:</span> <span class="nc">JSON</span>  <span class="p">-&gt;</span> <span class="nc">Result</span><span class="p">&lt;</span><span class="nc">Error</span><span class="p">,</span> <span class="nc">MyObject</span><span class="p">&gt;</span>
</code></pre></div></div>

<p>Of course, it’s likely that a programming language grammar is more
complex than the JSON grammar. But the two concepts are alike, and so are
the signatures.</p>

<p><a href="https://tree-sitter.github.io/tree-sitter/">Tree-sitter</a> too does something similar. It parses a string like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>"let x = 42;"
</code></pre></div></div>

<p>and emits a tree like:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(program
  (variable_declaration
    (lexical_declaration
      (identifier)
      (assignment_expression
        (number)))))
</code></pre></div></div>

<p>We can imagine the Tree-sitter grammar for F# as a function with this signature:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">val</span> <span class="n">treeSitter</span> <span class="p">:</span> <span class="nc">SourceCode</span> <span class="p">-&gt;</span> <span class="nc">Result</span><span class="p">&lt;</span><span class="nc">TreeSitterError</span><span class="p">,</span> <span class="nc">TreeSitterSExpression</span><span class="p">&gt;</span>
</code></pre></div></div>

<p>I guess you see the pattern.<br />
A parser is a function that takes loosely-structured data (usually
— but not necessarily — text), and tries to build a more
structured data out of it, accordingly to the rules of a formal
grammar.</p>

<h2 id="an-inherent-recursive-structure">An inherent recursive structure</h2>

<p>We say that the input data is loosely-structured because, in fact, it
is not granted to adhere to the rules of the chosen grammar. Indeed,
if it violates them, then we expect the parser to fail and to emit an
error, to help the user identify the syntax errors.</p>

<p>There are multiple approaches to parsing, including the renowned
Regular Expressions.<br />
Monadic Parser Combinators are a particularly fascinating one: they
are an example of <a href="https://en.wikipedia.org/wiki/Recursive_descent_parser">Recursive Descent
Parsers</a>. This means that no matter how
complex the parser for a grammar is, it is defined based on smaller,
simpler parsers, and those in turn are defined based on even smaller
and simpler ones, and so on recursively, down to the trivial parsers.<br />
You can see the same from the opposite perspective: starting from the
trivial parsers, by <em>combining</em> them together and then by combining
their results, recursively, the parser for any arbitrary grammar can
be built.</p>

<p>Now, if writing the trivial parsers is, well, trivial, the only
challenge that’s left is to learn how to <em>combine</em> parsers. That is,
how these Parsers Combinators work.</p>

<p>That’s the goal of this series.</p>

<h2 id="how-we-will-proceed">How we will proceed</h2>

<p>There are many similar series online, some specific to F# such as <a href="https://fsharpforfunandprofit.com/series/understanding-parser-combinators/">The
“Understanding Parser Combinators” series</a> by Scott
Wlaschin. This post tries to stand out in a few different ways:</p>

<ul>
  <li>
    <p>Many tutorials begin with writing a simple parser —
conventionally, the single-character parser. This does not.<br />
Instead, we will focus on combinators first, postponing the
implementation of concrete parsers to the last chapter. When I was
first introduced to parsers, I was just confused: what on earth does
it mean to parse a single character? What’s the point, where is this
leading me? My own ‘aha!’ moment came when I got how
composition turns tiny parsers into something actually useful.<br />
I hope I can help you skip past that initial disorientation entirely.</p>
  </li>
  <li>
    <p>We will write code with Test-Driven Development.<br />
Isn’t it ironic that we developers often lament the absence of tests
in our daily job projects and yet, when it comes to writing posts,
tutorials and books, we never address testing at all?</p>
  </li>
</ul>

<p>Ready? Let’s go started.</p>

<h1 id="references">References</h1>

<ul>
  <li><a href="https://en.wikipedia.org/wiki/Recursive_descent_parser">Recursive Descent Parser</a></li>
  <li><a href="https://tree-sitter.github.io/tree-sitter/">Tree-sitter</a></li>
  <li><a href="https://fsharpforfunandprofit.com/series/understanding-parser-combinators/">Scott Wlaschin - The “Understanding Parser Combinators” series</a></li>
</ul>

<h1 id="comments">Comments</h1>
<p><a href="https://github.com/arialdomartini/arialdomartini.github.io/discussions/33">GitHub Discussions</a></p>

<h2>Functional Programming For The Rest Os Us</h2>

<p>Interested in FP? Be the first to be notified when new introductory
articles on the topic are published.<br /></p>

<iframe class="newsletter-subscription" src="https://embeds.beehiiv.com/55b1bb2e-e731-466f-8d1e-82b51d67a9ef?slim=true" data-test-id="beehiiv-embed" height="52" frameborder="0" scrolling="no" style="margin: 0; margin-top:5px; border-radius: 0px !important; background-color: transparent;"></iframe>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="fsharp" /><category term="functional programming" /><category term="property-based testing" /><summary type="html"><![CDATA[You want to invent a new language, and you want to do this in F#, don’t you? And, of course, you want to base its parser on Monadic Parser Combinators. You’ve always wanted, just admit it.]]></summary></entry><entry><title type="html">Emacs: consult-line-symbol-at-point</title><link href="http://arialdomartini.github.io/consult-line-at-point" rel="alternate" type="text/html" title="Emacs: consult-line-symbol-at-point" /><published>2025-04-09T00:00:00+00:00</published><updated>2025-04-09T00:00:00+00:00</updated><id>http://arialdomartini.github.io/consult-line-at-point</id><content type="html" xml:base="http://arialdomartini.github.io/consult-line-at-point"><![CDATA[<p>I’m addicted to <a href="https://github.com/minad/consult">consult.el</a>. It is so convenient that when I
found out that <code class="language-plaintext highlighter-rouge">isearch-forward-symbol-at-point (M-s .)</code> was a thing,
I immediately felt the desire to integrate it with
consult.el. Luckily, this was way easier than I thought.</p>

<p>Let’s walk through the steps I took. As often happens with Emacs,
along the path of exploring its source code, we will find some random
pearls here and there to pick.</p>

<h2 id="tl-dr">TL; DR:</h2>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="s">"Search for a line matching the symbol found near point."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">consult-line</span>
   <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'symbol</span><span class="p">))))</span>
   
<span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s ."</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">consult-line-symbol-at-point</span><span class="p">)</span>
<span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s M-s ."</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">isearch-forward-symbol-at-point</span><span class="p">)</span>
</code></pre></div></div>

<!--more-->
<p>This issue is based on a lesson I got from <a href="https://protesilaos.com/">Protesilaos</a>.</p>

<h2 id="you-have-no-idea-how-powerful-isearch-is">You have no idea how powerful isearch is!</h2>
<p>I was fascinated by the post <a href="https://emacsredux.com/blog/2025/03/18/you-have-no-idea-how-powerful-isearch-is/">You have no idea how powerful isearch
is!</a> by <a href="https://emacsredux.com/">Bozhidar Batsov</a>. In fact, I really had
no idea.</p>

<p>One of the tricks he suggests is:</p>

<blockquote>
  <p>Type <code class="language-plaintext highlighter-rouge">M-s .</code> to search for the symbol at point.<br />
(useful in the context of programming languages)</p>
</blockquote>

<p>It’s very convenient: when your point is over a symbol, just hit <code class="language-plaintext highlighter-rouge">M-s .</code>
to find other occurrences. Emacs will do its best to figure out what
<em>symbol</em> means.</p>

<p><code class="language-plaintext highlighter-rouge">M-s .</code> (that is, <code class="language-plaintext highlighter-rouge">isearch-forward-symbol-at-point</code>) is so more
convenient than what I was used to do: once positioned on a
symbol,</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">C-=</code> (<code class="language-plaintext highlighter-rouge">er/expand-region</code>) to select it</li>
  <li><code class="language-plaintext highlighter-rouge">M-w</code> to copy it.</li>
  <li><code class="language-plaintext highlighter-rouge">C-s</code> to trigger <code class="language-plaintext highlighter-rouge">consult-line</code></li>
  <li><code class="language-plaintext highlighter-rouge">C-y</code> to use it as the search pattern.</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">M-s .</code> does the same in one single shot. With the only difference
that, alas!, it uses <code class="language-plaintext highlighter-rouge">isearch-forward</code> instead of <code class="language-plaintext highlighter-rouge">consult-line</code>.<br />
As I mentioned, once tried <code class="language-plaintext highlighter-rouge">consult.el</code>, I could not do without it
anymore. <del>Unfortunately, <code class="language-plaintext highlighter-rouge">consult.el</code> does not provide
<code class="language-plaintext highlighter-rouge">consult-line-symbol-at-point</code></del>.</p>

<p>How hard is it to write it?</p>

<p>Edit: it turns out (thank you @Crandel!) that the consult.el <a href="https://github.com/minad/consult/blob/30a42ac8f3d42f653eda234ee538c1960704f4f2/README.org#fine-tuning-of-individual-commands">README</a>
suggests obtaining this result simply with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">consult-customize</span>
 <span class="nv">consult-line</span>
 <span class="ss">:add-history</span> <span class="p">(</span><span class="nv">seq-some</span> <span class="nf">#'</span><span class="nv">thing-at-point</span> <span class="o">'</span><span class="p">(</span><span class="nv">region</span> <span class="nc">symbol</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">defalias</span> <span class="ss">'consult-line-thing-at-point</span> <span class="ss">'consult-line</span><span class="p">)</span>

<span class="p">(</span><span class="nv">consult-customize</span>
 <span class="nv">consult-line-thing-at-point</span>
 <span class="ss">:initial</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'symbol</span><span class="p">))</span>
</code></pre></div></div>

<p>Although next time I should RTFM!, I don’t regret not knowing this:
learning it by hacking has been a rewarding experience.</p>

<h2 id="how-does-isearch-forward-symbol-at-point-work">How does <code class="language-plaintext highlighter-rouge">isearch-forward-symbol-at-point</code> work?</h2>
<p>It makes sense to figure out first how
<code class="language-plaintext highlighter-rouge">isearch-forward-symbol-at-point</code> works. Which you can do with
either:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">M-x describe-key RET M-s .</code></li>
  <li><code class="language-plaintext highlighter-rouge">M-x describe-function isearch-forward-symbol-at-point</code></li>
</ul>

<p>(in turn, <code class="language-plaintext highlighter-rouge">describe-key</code> and <code class="language-plaintext highlighter-rouge">describe-function</code> are conveniently
bound respectively to <code class="language-plaintext highlighter-rouge">C-h k</code> and <code class="language-plaintext highlighter-rouge">C-h f</code>). You will get this
documentation:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>M-s . runs the command isearch-forward-symbol-at-point (found in
global-map), which is an interactive native-compiled Lisp function in
`isearch.el`.

It is bound to M-s ..

(isearch-forward-symbol-at-point &amp;optional ARG)
</code></pre></div></div>

<p>From this help page, you can jump to the source code either:</p>

<ul>
  <li>hitting <code class="language-plaintext highlighter-rouge">s</code>.</li>
  <li>running <code class="language-plaintext highlighter-rouge">M-x help-view-source</code>.</li>
  <li>hitting Enter while hovering the link <code class="language-plaintext highlighter-rouge">isearch.el</code>.</li>
</ul>

<p>Fine. Here’s the code:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">isearch-forward-symbol-at-point</span> <span class="p">(</span><span class="k">&amp;optional</span> <span class="nv">arg</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="s">"P"</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">isearch-forward-symbol</span> <span class="no">nil</span> <span class="mi">1</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">bounds</span> <span class="p">(</span><span class="nv">find-tag-default-bounds</span><span class="p">))</span>
        <span class="p">(</span><span class="nb">count</span> <span class="p">(</span><span class="nb">and</span> <span class="nv">arg</span> <span class="p">(</span><span class="nv">prefix-numeric-value</span> <span class="nv">arg</span><span class="p">))))</span>
    <span class="p">(</span><span class="nb">cond</span>
     <span class="p">(</span><span class="nv">bounds</span>
      <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">&lt;</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">bounds</span><span class="p">)</span> <span class="p">(</span><span class="nv">point</span><span class="p">))</span>
	<span class="p">(</span><span class="nv">goto-char</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">bounds</span><span class="p">)))</span>
      <span class="p">(</span><span class="nv">isearch-yank-string</span>
       <span class="p">(</span><span class="nv">buffer-substring-no-properties</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">bounds</span><span class="p">)</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">bounds</span><span class="p">)))</span>
      <span class="p">(</span><span class="nb">when</span> <span class="nb">count</span>
        <span class="p">(</span><span class="nv">isearch-repeat-forward</span> <span class="nb">count</span><span class="p">)))</span>
     <span class="p">(</span><span class="no">t</span>
      <span class="p">(</span><span class="k">setq</span> <span class="nv">isearch-error</span> <span class="s">"No symbol at point"</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">isearch-push-state</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">isearch-update</span><span class="p">)))))</span>
</code></pre></div></div>

<p>Spitting blood (I’m not that good at Lisp), I could extract the part
that identifies the symbol at point with this function:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">get-symbol-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">bounds</span> <span class="p">(</span><span class="nv">find-tag-default-bounds</span><span class="p">)))</span>
    <span class="p">(</span><span class="nb">cond</span>
     <span class="p">(</span><span class="nv">bounds</span>
      <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">&lt;</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">bounds</span><span class="p">)</span> <span class="p">(</span><span class="nv">point</span><span class="p">))</span>
	<span class="p">(</span><span class="nv">goto-char</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">bounds</span><span class="p">)))</span>
       <span class="p">(</span><span class="nv">buffer-substring-no-properties</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">bounds</span><span class="p">)</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">bounds</span><span class="p">)))</span>
     <span class="p">(</span><span class="no">t</span> <span class="p">()))))</span>
</code></pre></div></div>

<p>I’m honest: I cannot understand it completely. However, it’s easy to
verify that it actually works:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">show-symbol-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">message</span> <span class="s">"%s"</span> <span class="p">(</span><span class="nv">get-symbol-at-point</span><span class="p">)))</span>
</code></pre></div></div>

<p>Move the point on any symbol and execute <code class="language-plaintext highlighter-rouge">M-x show-symbol-at-point
RET</code>. Cool: sounds like it is a good starting point.</p>

<h2 id="emacs-geological-layers">Emacs’ geological layers?</h2>
<p>My good friend <a href="https://protesilaos.com/">Prot</a> brought to my attention that in fact a
function <code class="language-plaintext highlighter-rouge">symbol-at-point</code> is built-in in Emacs. It is part of
<a href="https://www.emacswiki.org/emacs/ThingAtPoint">thingatpt.el</a> and a <code class="language-plaintext highlighter-rouge">git blame</code> reveals it has been
introduced 19 years ago. Indeed, it is used here and there (check the
code of <code class="language-plaintext highlighter-rouge">org-open-at-point-global</code>, <code class="language-plaintext highlighter-rouge">describe-symbol</code>,
<code class="language-plaintext highlighter-rouge">imenu--completion-buffer</code> for example). It’s not completely clear to
me why it has not been used in <code class="language-plaintext highlighter-rouge">isearch-forward-symbol-at-point</code> too.
Maybe there are historical reasons. This confuses me, since
<code class="language-plaintext highlighter-rouge">isearch-forward-symbol-at-point</code> has been introduced after
<code class="language-plaintext highlighter-rouge">thingatpt.el</code>.</p>

<p>Whatever.<br />
Let’s try it out, replacing my horrible custom <code class="language-plaintext highlighter-rouge">get-symbol-at-point</code>
with the standard <code class="language-plaintext highlighter-rouge">symbol-at-point</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">show-symbol-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">message</span> <span class="s">"%s"</span> <span class="p">(</span><span class="nv">symbol-at-point</span><span class="p">)))</span>
</code></pre></div></div>

<p>Works like a charm! Good: we know how to get the symbol at point.
We will have to pass it somehow to <code class="language-plaintext highlighter-rouge">consult-line</code>.</p>

<h2 id="how-does-consult-line-work">How does <code class="language-plaintext highlighter-rouge">consult-line</code> work?</h2>
<p>Now, if we want to build a <code class="language-plaintext highlighter-rouge">consult-line-symbol-at-point</code> function,
we’d better have a look to <code class="language-plaintext highlighter-rouge">consult-line</code>’s source code first.</p>

<p>Run <code class="language-plaintext highlighter-rouge">M-x describe-function RET consult-line RET</code>, then get to the code
with <code class="language-plaintext highlighter-rouge">M-x help-view-source RET</code> (or <code class="language-plaintext highlighter-rouge">s</code>).</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line</span> <span class="p">(</span><span class="k">&amp;optional</span> <span class="nv">initial</span> <span class="nv">start</span><span class="p">)</span>
  <span class="s">"Search for a matching line.

Depending on the setting `consult-point-placement' the command
jumps to the beginning or the end of the first match on the line
or the line beginning.  The default candidate is the non-empty
line next to point.  This command obeys narrowing.  Optional
INITIAL input can be provided.  The search starting point is
changed if the START prefix argument is set.  The symbol at point
and the last `isearch-string' is added to the future history."</span>

  <span class="p">(</span><span class="nv">interactive</span> <span class="p">(</span><span class="nb">list</span> <span class="no">nil</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nb">not</span> <span class="nv">current-prefix-arg</span><span class="p">))))</span>
  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">curr-line</span> <span class="p">(</span><span class="nv">line-number-at-pos</span> <span class="p">(</span><span class="nv">point</span><span class="p">)</span> <span class="nv">consult-line-numbers-widen</span><span class="p">))</span>
         <span class="p">(</span><span class="nv">top</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nb">eq</span> <span class="nv">start</span> <span class="nv">consult-line-start-from-top</span><span class="p">)))</span>
         <span class="p">(</span><span class="nv">candidates</span> <span class="p">(</span><span class="nv">consult--slow-operation</span> <span class="s">"Collecting lines..."</span>
                       <span class="p">(</span><span class="nv">consult--line-candidates</span> <span class="nv">top</span> <span class="nv">curr-line</span><span class="p">))))</span>
    <span class="p">(</span><span class="nv">consult--read</span>
     <span class="nv">candidates</span>
     <span class="ss">:prompt</span> <span class="p">(</span><span class="k">if</span> <span class="nv">top</span> <span class="s">"Go to line from top: "</span> <span class="s">"Go to line: "</span><span class="p">)</span>
     <span class="ss">:annotate</span> <span class="p">(</span><span class="nv">consult--line-prefix</span> <span class="nv">curr-line</span><span class="p">)</span>
     <span class="ss">:category</span> <span class="ss">'consult-location</span>
     <span class="ss">:sort</span> <span class="no">nil</span>
     <span class="ss">:require-match</span> <span class="no">t</span>
     <span class="c1">;; Always add last `isearch-string' to future history</span>
     <span class="ss">:add-history</span> <span class="p">(</span><span class="nb">list</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'symbol</span><span class="p">)</span> <span class="nv">isearch-string</span><span class="p">)</span>
     <span class="ss">:history</span> <span class="o">'</span><span class="p">(</span><span class="ss">:input</span> <span class="nv">consult--line-history</span><span class="p">)</span>
     <span class="ss">:lookup</span> <span class="nf">#'</span><span class="nv">consult--line-match</span>
     <span class="ss">:default</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">candidates</span><span class="p">)</span>
     <span class="c1">;; Add `isearch-string' as initial input if starting from Isearch</span>
     <span class="ss">:initial</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">initial</span>
                  <span class="p">(</span><span class="nb">and</span> <span class="nv">isearch-mode</span>
                       <span class="p">(</span><span class="nb">prog1</span> <span class="nv">isearch-string</span> <span class="p">(</span><span class="nv">isearch-done</span><span class="p">))))</span>
     <span class="ss">:state</span> <span class="p">(</span><span class="nv">consult--location-state</span> <span class="nv">candidates</span><span class="p">))))</span>
</code></pre></div></div>

<p>That’s it, not so huge, afterall. Basically, <code class="language-plaintext highlighter-rouge">consult-line</code> is just a
thin wrapper around the internal function <code class="language-plaintext highlighter-rouge">consult--read</code>. We found
something similar when we wanted to replace <code class="language-plaintext highlighter-rouge">completing-read</code> with a
consult function, for getting
real-time preview in <a href="/emacs-zoom#completing-read">Emacs: let’s zoom</a>.<br />
In the worst hypothesis, we could do the same and use this internal
<code class="language-plaintext highlighter-rouge">consult--read</code>, passing it the symbol at point. But this is not even
necessary. Notice the first <code class="language-plaintext highlighter-rouge">consult-line</code> parameter, <code class="language-plaintext highlighter-rouge">initial</code>? If
it’s not <code class="language-plaintext highlighter-rouge">nil</code>, then it will be used as the initial pattern.<br />
Let’s see how it works. Evaluate this with <code class="language-plaintext highlighter-rouge">C-x C-e</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">consult-line</span> <span class="s">"whatever"</span><span class="p">)</span>
</code></pre></div></div>

<p>Cool. It seems that really all we have to do is to feed <code class="language-plaintext highlighter-rouge">consult-line</code>
with <code class="language-plaintext highlighter-rouge">symbol-at-point</code> as the initial value.</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="s">"Search for a line matching the symbol found near point."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nv">symbol-at-point</span><span class="p">)))</span>
   
<span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s ."</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">consult-line-symbol-at-point</span><span class="p">)</span>
</code></pre></div></div>

<p>Try it out. Nope. We get an</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apply: Wrong type argument: stringp, Try
</code></pre></div></div>

<p>This is because <code class="language-plaintext highlighter-rouge">(symbol-at-point)</code> returns a <code class="language-plaintext highlighter-rouge">symbol</code>, whereas
<code class="language-plaintext highlighter-rouge">consult-line</code> wants a <code class="language-plaintext highlighter-rouge">string</code>. Fine: there must be a function to
convert symbols to strings, right? I would try with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">M-x</span> <span class="nv">describe-function</span> <span class="nv">RET</span> <span class="nc">symbol</span>
</code></pre></div></div>

<p>to list the symbol-related functions. <code class="language-plaintext highlighter-rouge">symbol-name</code> sounds like a good
candidate. Its documentation says:</p>

<blockquote>
  <p>Return SYMBOL’s name, a string.</p>
</blockquote>

<p>Let’t try it out:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="s">"Search for a line matching the symbol found near point."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="p">(</span><span class="nv">symbol-at-point</span><span class="p">))))</span>
   
<span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s ."</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">consult-line-symbol-at-point</span><span class="p">)</span>
</code></pre></div></div>

<p>Woah. We are almost there.</p>

<h2 id="nil">nil!</h2>
<p>Does this work when there is no symbol at point? <code class="language-plaintext highlighter-rouge">symbol-at-point</code>
declares:</p>

<blockquote>
  <p>Return the symbol at point, or nil if none is found.</p>
</blockquote>

<p><code class="language-plaintext highlighter-rouge">(consult-line)</code> happily works when the <code class="language-plaintext highlighter-rouge">initial</code> pattern is <code class="language-plaintext highlighter-rouge">nil</code>
— or if it omitted. But the problem in our code is with
<code class="language-plaintext highlighter-rouge">symbol-name</code>: <code class="language-plaintext highlighter-rouge">(symbol-name nil)</code> is <code class="language-plaintext highlighter-rouge">"nil"</code>, as a string. So
consult.el would search for that string. Mumble mumble, shall we raise
an error, in that case?</p>

<h2 id="dwim">DWIM</h2>
<p>There’s a better alternative: to implement a <a href="https://www.emacswiki.org/emacs/DoWhatIMean">Do What I Mean</a>
behavior. That is, if there is no symbol at point, <code class="language-plaintext highlighter-rouge">M-s .</code> shall act
as a standard <code class="language-plaintext highlighter-rouge">consult-line</code>, if it’s over a symbol, it would search
for that symbol.</p>

<p>We may use an <code class="language-plaintext highlighter-rouge">if</code> clause:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="s">"Search for a line matching the symbol found near point."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nc">symbol</span> <span class="p">(</span><span class="nv">symbol-at-point</span><span class="p">)))</span>
    <span class="p">(</span><span class="k">if</span> <span class="nc">symbol</span>
        <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="nc">symbol</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">consult-line</span><span class="p">))))</span>
</code></pre></div></div>

<p>Now, an <code class="language-plaintext highlighter-rouge">if</code> nested in a <code class="language-plaintext highlighter-rouge">let</code> can be shortened with a <code class="language-plaintext highlighter-rouge">if-let</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="s">"Search for a line matching the symbol found near point."</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  
  <span class="p">(</span><span class="nv">if-let</span> <span class="p">((</span><span class="nc">symbol</span> <span class="p">(</span><span class="nv">symbol-at-point</span><span class="p">)))</span>
        <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="nc">symbol</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">consult-line</span><span class="p">)))</span>
</code></pre></div></div>

<p>But we can do better than this. We can remove the duplicated call to
<code class="language-plaintext highlighter-rouge">consult-line</code> swapping <code class="language-plaintext highlighter-rouge">if</code> and <code class="language-plaintext highlighter-rouge">consult-line</code>, playing with
the fact that:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">if</span> <span class="kt">condition</span>
    <span class="p">(</span><span class="k">function</span> <span class="nv">when-true</span><span class="p">)</span>
  <span class="p">(</span><span class="k">function</span> <span class="nv">when-false</span><span class="p">))</span>
</code></pre></div></div>

<p>can be always written as:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">function</span>
 <span class="p">(</span><span class="k">if</span> <span class="kt">condition</span> 
     <span class="nv">when-true</span>
   <span class="nv">when-false</span><span class="p">)</span>
</code></pre></div></div>

<p>Here we go:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nc">symbol</span> <span class="p">(</span><span class="nv">symbol-at-point</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">consult-line</span>
     <span class="p">(</span><span class="k">if</span> <span class="nc">symbol</span>
         <span class="p">(</span><span class="nb">symbol-name</span> <span class="nc">symbol</span><span class="p">)</span>
       <span class="p">()))))</span>
</code></pre></div></div>

<p>Now,</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">if</span> <span class="kt">condition</span> <span class="nv">when-true</span> <span class="p">())</span><span class="err">)</span>
</code></pre></div></div>

<p>can be shortened as:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">when</span> <span class="kt">condition</span> <span class="nv">when-true</span><span class="p">)</span>
</code></pre></div></div>

<p>So:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nc">symbol</span> <span class="p">(</span><span class="nv">symbol-at-point</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nb">when</span> <span class="nc">symbol</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="nc">symbol</span><span class="p">)))))</span>
</code></pre></div></div>

<p>Now, if you are curious as I am, it’s impossible not to take a closer
look to the code of <code class="language-plaintext highlighter-rouge">symbol-at-point</code>. Which reveals a possible
further improvement.</p>

<h2 id="how-does-symbol-at-point-work">How does <code class="language-plaintext highlighter-rouge">symbol-at-point</code> work?</h2>
<p>It turns out that also <code class="language-plaintext highlighter-rouge">symbol-at-point</code> is just a little wrapper, in
this case around the more generic <code class="language-plaintext highlighter-rouge">thing-at-point</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">symbol-at-point</span> <span class="p">()</span>
  <span class="s">"Return the symbol at point, or nil if none is found."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">thing</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'symbol</span><span class="p">)))</span>
    <span class="p">(</span><span class="k">if</span> <span class="nv">thing</span> <span class="p">(</span><span class="nb">intern</span> <span class="nv">thing</span><span class="p">))))</span>
</code></pre></div></div>

<p>You see that call to <code class="language-plaintext highlighter-rouge">intern</code>? If you check <code class="language-plaintext highlighter-rouge">intern</code>’s documentation
(<code class="language-plaintext highlighter-rouge">C-h f intern RET</code>), you will read:</p>

<blockquote>
  <p>Return the canonical symbol whose name is STRING.</p>
</blockquote>

<p>Now we see why we needed to invoke <code class="language-plaintext highlighter-rouge">symbol-name</code>! <code class="language-plaintext highlighter-rouge">symbol-at-point</code>
converts the string to a symbol, so we needed <code class="language-plaintext highlighter-rouge">symbol-name</code> to get the
string back! It makes sense to directly invoke <code class="language-plaintext highlighter-rouge">thing-at-point</code>, then:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nc">symbol</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'symbol</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nb">when</span> <span class="nc">symbol</span> <span class="nc">symbol</span><span class="p">))))</span>
</code></pre></div></div>

<p>Wait a second: what does <code class="language-plaintext highlighter-rouge">thing-at-point</code> return, when there is no
thing at point? Move the point in an empty part of the buffer,
then invoke it with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">M-x</span> <span class="nv">eval-expression</span> <span class="nv">RET</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'symbol</span><span class="p">)</span>
</code></pre></div></div>

<p>It returns <code class="language-plaintext highlighter-rouge">nil</code>! We are lucky: it means that we don’t need all the
ceremony about creating the variable <code class="language-plaintext highlighter-rouge">symbol</code> and checking its value
with <code class="language-plaintext highlighter-rouge">when</code>. We can simplify our code as:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-symbol-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'symbol</span><span class="p">)))</span>
</code></pre></div></div>

<p>There is no greater pleasure than deleting code, is there?</p>

<h2 id="have-i-already-told-you-are-curious-as-a-monkey">Have I already told you are curious as a monkey?</h2>
<p>I know what you are asking yourself: what is that <code class="language-plaintext highlighter-rouge">'symbol</code> argument
we passed to <code class="language-plaintext highlighter-rouge">thing-at-point</code>? Sounds like the <em>kind of thing</em> we want
to detect.<br />
And what about that part of the <code class="language-plaintext highlighter-rouge">thing-at-point</code> documentation that
mentions other possible values?</p>

<blockquote>
  <p>THING should be a symbol specifying a type of syntactic entity.
Possibilities include ‘symbol’, ‘list’, ‘sexp’, ‘defun’, ‘filename’,
‘existing-filename’, ‘url’, ‘email’, ‘uuid’, ‘word’, ‘sentence’,
‘whitespace’, ‘line’, ‘number’, ‘face’ and ‘page’.</p>
</blockquote>

<p>And, finally, what about this intriguing invitation?</p>

<blockquote>
  <p>See the file ‘thingatpt.el’ for documentation
on how to define a symbol as a valid THING.</p>
</blockquote>

<p>I can not resist, can you? We have to try those other <em>syntactic
entity</em> types, then we have to challenge ourselves defining our first
custom <em>thing-at-point</em>.</p>

<h2 id="you-are-repetitive-arialdo">You are repetitive, Arialdo!</h2>
<p>Let me find out how many times I kept repeating “Try yourself” in his
post.</p>

<p>Define:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-sentence-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'sentence</span><span class="p">)))</span>
</code></pre></div></div>

<p>Try yourself.</p>

<p>Notice how we are asking <code class="language-plaintext highlighter-rouge">thing-at-point</code> to detect a whole sentence,
not just the single symbol at point.</p>

<p><img src="static/img/emacs/consult-line-at-point/try-yourself.png" alt="consult-line-sentence-at-point in action" width="100%" /></p>

<p>Cool. I’m not that repetitive, after all.<br />
Honestly, I have no idea how this would be useful. Maybe detecting
sexps could come more in handy:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-sexp-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'sexp</span><span class="p">)))</span>
</code></pre></div></div>

<p><img src="static/img/emacs/consult-line-at-point/sexp-at-point.png" alt="consult-line-sexp-at-point in action" width="100%" /></p>

<p>You got the idea.</p>

<p>This bears the question: how to define a new custom
type of thing? We have no choice but to try.<br />
The documentation is clear:</p>

<blockquote>
  <p>See the file ‘thingatpt.el’ for documentation
on how to define a symbol as a valid THING.</p>
</blockquote>

<p>So, let’s read the library code! <code class="language-plaintext highlighter-rouge">M-x find-library RET
thingatpt RET</code></p>

<h2 id="providers">Providers</h2>
<p>Browsing around, you should stumble upon this variable:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defvar</span> <span class="nv">thing-at-point-provider-alist</span> <span class="no">nil</span>
  <span class="err">"</span><span class="nv">Alist</span> <span class="nv">of</span> <span class="nv">providers</span> <span class="nv">for</span> <span class="nv">returning</span> <span class="nv">a</span> <span class="nv">\"thing\"</span> <span class="nv">at</span> <span class="nv">point.</span>
<span class="nv">This</span> <span class="nv">variable</span> <span class="nv">can</span> <span class="nv">be</span> <span class="nb">set</span> <span class="nv">globally,</span> <span class="nb">or</span> <span class="nv">appended</span> <span class="nv">to</span> <span class="nv">buffer-locally</span>
<span class="nv">by</span> <span class="nv">modes,</span> <span class="nv">to</span> <span class="nb">provide</span> <span class="nv">functions</span> <span class="nv">that</span> <span class="nv">will</span> <span class="nb">return</span> <span class="nv">a</span> <span class="nv">\"thing\"</span> <span class="nv">at</span>
<span class="nv">point.</span>  <span class="nv">The</span> <span class="nb">first</span> <span class="nv">provider</span> <span class="nv">for</span> <span class="k">the</span> <span class="nv">\"thing\"</span> <span class="nv">that</span> <span class="nv">returns</span> <span class="nv">a</span>
<span class="nv">non-nil</span> <span class="nv">value</span> <span class="nv">wins.</span>

<span class="nv">For</span> <span class="nv">instance,</span> <span class="nv">a</span> <span class="nv">major</span> <span class="nv">mode</span> <span class="nv">could</span> <span class="nv">say:</span>

<span class="p">(</span><span class="nv">setq-local</span> <span class="nv">thing-at-point-provider-alist</span>
            <span class="p">(</span><span class="nb">append</span> <span class="nv">thing-at-point-provider-alist</span>
                    <span class="o">'</span><span class="p">((</span><span class="nv">url</span> <span class="o">.</span> <span class="nv">my-mode--url-at-point</span><span class="p">))))</span>

<span class="nv">to</span> <span class="nb">provide</span> <span class="nv">a</span> <span class="nv">way</span> <span class="nv">to</span> <span class="nb">get</span> <span class="nv">an</span> <span class="o">`</span><span class="nv">url</span><span class="o">'</span> <span class="nv">at</span> <span class="nv">point</span> <span class="nv">in</span> <span class="nv">that</span> <span class="nv">mode.</span>  <span class="nv">The</span>
<span class="nv">provider</span> <span class="nv">functions</span> <span class="nv">are</span> <span class="nv">called</span> <span class="nv">with</span> <span class="nv">no</span> <span class="nv">parameters</span> <span class="nv">at</span> <span class="k">the</span> <span class="nv">point</span> <span class="nv">in</span>
<span class="nv">question.</span>
</code></pre></div></div>

<p>Sounds like our culprit.</p>

<p>If you recap what we discovered until this point, you probably agree
that this is a beautiful design trait of Emacs:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">isearch-forward-symbol-at-point</code> focuses on <em>searching</em> things,
seen as strings.</li>
  <li><code class="language-plaintext highlighter-rouge">thing-at-point</code> focuses on returning that <em>thing</em>. It does that by
delegating the job to a customizable collection of <em>thing</em>-providers.</li>
  <li>Each <em>thing</em>-provider implements some custom, arbitrary logic to
detect a <em>thing</em> given the position in a buffer.</li>
</ul>

<p>Indeed, we were able to easily create our
<code class="language-plaintext highlighter-rouge">consult-line-symbol-at-point</code> because of this modular nature.</p>

<p>Time to challenge ourselves to define a <em>thing</em> that is not natively
supported by <code class="language-plaintext highlighter-rouge">isearch-forward-symbol-at-point</code>.</p>

<h2 id="a-provider-for-literal-strings-via-tree-sitter">A provider for literal strings, via Tree Sitter</h2>
<p>Imagine we want to write <code class="language-plaintext highlighter-rouge">consult-line-literal-string-at-point</code>, to
search for occurrences of the whole literal string at point, whatever
buffer’s programming language defines as a <em>literal string</em>. You could
use it to find duplicated strings in code:</p>

<p><img src="static/img/emacs/consult-line-at-point/literal-string-at-point.png" alt="consult-line-literal-string-at-point in action" width="100%" /></p>

<p>What we should do is to define a new provider,
<code class="language-plaintext highlighter-rouge">ts-get-literal-string-at-point</code>, a function whose goal is to return
the literal string around the point. Notice the <code class="language-plaintext highlighter-rouge">ts-</code> in the name?
That stands for Tree-sitter. Indeed, we will rely on whatever
Tree-sitter grammar is active in the current buffer.</p>

<p>Once defined the provider, we will need to register it in the list of
the global or the local <em>thing-at-point</em> providers. At that moment, we
will get the chance to associate it to a symbol of our choice (we will
use <code class="language-plaintext highlighter-rouge">str_lit</code>).</p>

<p>Once done that, <code class="language-plaintext highlighter-rouge">thing-at-point</code> will be able to detect literal
strings at point (using the symbol we chose).</p>

<p>(Pause a minute to reflect again on the modular design of Emacs: Tree
Sitter has been conceived in 2018, independently from Emacs and when
Emacs was already 34. What we are really doing here is connecting some
prehistoric Emacs machinery with Tree-sitter, the brand new kid on the
block. There must be some deep beauty in the Emacs design if this
works without any gimmick).</p>

<p>So, here’s the provider:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">ts-get-literal-string-at-point</span> <span class="p">()</span>
  <span class="s">"Return the string node at point using Tree-sitter, or nil if none is found."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">node</span> <span class="p">(</span><span class="nv">treesit-node-at</span> <span class="p">(</span><span class="nv">point</span><span class="p">))))</span>
    <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">equal</span> <span class="p">(</span><span class="nv">treesit-node-type</span> <span class="nv">node</span><span class="p">)</span> <span class="s">"str_lit"</span><span class="p">)</span>
          <span class="p">(</span><span class="nv">treesit-node-text</span> <span class="nv">node</span><span class="p">))))</span>
</code></pre></div></div>

<p>It works like this:</p>

<ul>
  <li>It asks Tree-sitter to get the node at point, with <code class="language-plaintext highlighter-rouge">(treesit-node-at
(point))</code>.</li>
  <li>It checks the node type is of a literal string, <code class="language-plaintext highlighter-rouge">(equal ... "str_lit")</code>,</li>
  <li>then it returns its content <code class="language-plaintext highlighter-rouge">(treesit-node-text node)</code>.</li>
  <li>Otherwise, it just returns <code class="language-plaintext highlighter-rouge">nil</code>.</li>
</ul>

<p>And here is how we can (globally) register it:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">thing-at-point-provider-alist</span>
            <span class="p">(</span><span class="nb">append</span> <span class="nv">thing-at-point-provider-alist</span>
                    <span class="o">'</span><span class="p">((</span><span class="nv">str_lit</span> <span class="o">.</span> <span class="nv">ts-get-literal-string-at-point</span><span class="p">))))</span>
</code></pre></div></div>

<p>In a real case scenario, this would be done by a major mode, so most
likely using <code class="language-plaintext highlighter-rouge">setq-local</code> instead of <code class="language-plaintext highlighter-rouge">setq</code>, inside a hook. If you are
curious how major modes and hooks work in Emacs, you might give a read
to <a href="emacs-hooks">Emacs: how to
activate the functionality X for all files of type
Y?</a>.</p>

<p>Finally, let’s have a function connecting <code class="language-plaintext highlighter-rouge">thing-at-point</code> against
<code class="language-plaintext highlighter-rouge">str_lit</code> with <code class="language-plaintext highlighter-rouge">consult</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">consult-line-literal-string-at-point</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">consult-line</span> <span class="p">(</span><span class="nv">thing-at-point</span> <span class="ss">'str_lit</span><span class="p">)))</span>


<span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">"M-s C-s ."</span><span class="p">)</span> <span class="nf">#'</span><span class="nv">consult-line-literal-string-at-point</span><span class="p">)</span>
</code></pre></div></div>

<p>It really works! Try yourself.</p>

<p>(Ouch! I repeated myself)</p>

<h1 id="references">References</h1>

<ul>
  <li><a href="https://github.com/minad/consult">consult</a></li>
  <li><a href="https://emacsredux.com/blog/2025/03/18/you-have-no-idea-how-powerful-isearch-is/">You have no idea how powerful isearch is!</a></li>
  <li><a href="https://protesilaos.com/">Protesilaos Stavrou</a></li>
  <li><a href="https://www.emacswiki.org/emacs/ThingAtPoint">thingatpt.el</a></li>
  <li><a href="https://www.emacswiki.org/emacs/DoWhatIMean">DWIM</a></li>
  <li><a href="https://emacsredux.com/blog/2025/03/18/you-have-no-idea-how-powerful-isearch-is/">Bozhidar Batzov - Emacs Redux</a></li>
</ul>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="emacs" /><category term="lisp" /><summary type="html"><![CDATA[I’m addicted to consult.el. It is so convenient that when I found out that isearch-forward-symbol-at-point (M-s .) was a thing, I immediately felt the desire to integrate it with consult.el. Luckily, this was way easier than I thought. Let’s walk through the steps I took. As often happens with Emacs, along the path of exploring its source code, we will find some random pearls here and there to pick. TL; DR: (defun consult-line-symbol-at-point () "Search for a line matching the symbol found near point." (interactive) (consult-line (or (thing-at-point 'symbol)))) (global-set-key (kbd "M-s .") #'consult-line-symbol-at-point) (global-set-key (kbd "M-s M-s .") #'isearch-forward-symbol-at-point)]]></summary></entry><entry><title type="html">Emacs: a peek under Imenu’s hood</title><link href="http://arialdomartini.github.io/emacs-imenu" rel="alternate" type="text/html" title="Emacs: a peek under Imenu’s hood" /><published>2025-01-27T00:00:00+00:00</published><updated>2025-01-27T00:00:00+00:00</updated><id>http://arialdomartini.github.io/emacs-imenu</id><content type="html" xml:base="http://arialdomartini.github.io/emacs-imenu"><![CDATA[<p>I promised myself to write a Tree-sitter major mode for F#. I’ve been
told that it should not be such an insurmountable endeavour, but given
that I start from the scratch, along the journey I will need to learn
a bunch of new topics from the ground up. Nice, that’s why we use
Emacs, right?</p>

<p>For each of those themes, I will publish a little blog post to share
the lesson learnt.</p>

<p>Today it’s the Imenu’s turn.</p>

<!--more-->

<p>Imenu is an Emacs feature that produces menu items for accessing
locations in buffers. Here’s the one for this very blog post:</p>

<p><img width="100%" src="/static/img/emacs/imenu/imenu.png" /></p>

<p>If you are a programmer it is very likely that you have switched the
visual menu off with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">-1</span><span class="p">)</span>
</code></pre></div></div>

<p>and that you prefer using the keyboard. Luckily for us keeb fans,
Imenu happily works in the minibuffer too. Try yourself:</p>

<ul>
  <li>Open a file for which you have a major mode installed.</li>
  <li>Run <code class="language-plaintext highlighter-rouge">M-x imenu</code>.</li>
</ul>

<p>If you have <a href="https://github.com/minad/consult">consult.el</a> installed, you would surely prefer
<code class="language-plaintext highlighter-rouge">M-x consult-imenu</code> which offers narrowing and real-time preview.</p>

<p>Here’s how <code class="language-plaintext highlighter-rouge">consult-imenu</code> looks like while visiting <code class="language-plaintext highlighter-rouge">imenu.el</code>:</p>

<p><img width="100%" src="/static/img/emacs/imenu/consult-imenu.png" /></p>

<p>Why would an F# mode need Imenu in the first place? Because you would
use it to jump to function definitions, variables and other structural
elements of the code. Together with <code class="language-plaintext highlighter-rouge">consult-outline</code> this is one of
the most convenient ways to reason about the structure of the code
module you are visualizing.</p>

<p>So, our long term goal is to learn how to extract the structural
elements of an F# buffer and to accordingly configure Imenu.</p>

<p>It turns out that:</p>

<ul>
  <li>Imenu was initially conceived to work mainly using regular
expressions.</li>
  <li>Tree-sitter offers a completely different way to extract structural
elements from code, which saves major modes developers from dealing
with regular expressions (because, as the saying goes “the plural of
regex is regrets”).</li>
</ul>

<p>We start our journey learning the classical way to use Imenu. We will
cover the integration between Tree-sitter and Imenu in a second blog post.</p>

<h2 id="imenu">Imenu</h2>

<p>Let’s start with a simple case. Open the scratch buffer and past this
content:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(defun greet ()
  (message "Hello, world!"))

(defun be-kind ()
  (message "OK, I will"))
</code></pre></div></div>

<p>Then run <code class="language-plaintext highlighter-rouge">imenu</code>: you should see those 2 functions listed. Selecting
one, will get you to its definition. This is basically what Imenu does.</p>

<p>Besided <em>what</em> it does, we want to learn more <em>how</em> it actually works.
So, let’s start delving into some details.</p>

<h2 id="imenuindex-alist">imenu–index-alist</h2>
<p>At its core, Imenu just displays the content of the (private) variable
<code class="language-plaintext highlighter-rouge">imenu--index-alist</code>. Try yourself. Again in the scratch buffer, paste and
evaluate (<code class="language-plaintext highlighter-rouge">C-x C-e</code>) the following:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">imenu--index-alist</span>
  <span class="o">`</span><span class="p">((</span><span class="s">"beginning"</span> <span class="o">.</span> <span class="mi">1</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"third char"</span> <span class="o">.</span> <span class="mi">3</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"fifth char"</span> <span class="o">.</span> <span class="mi">5</span><span class="p">)))</span>
</code></pre></div></div>

<p>Then execute <code class="language-plaintext highlighter-rouge">imenu</code> again. No matter what the Imenu content was
before, by overwriting <code class="language-plaintext highlighter-rouge">imenu--index-alist</code> you have just hijacked it.
You can even display it in the visual menu bar:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">menu-bar-mode</span> <span class="mi">1</span><span class="p">)</span>
<span class="p">(</span><span class="nv">imenu-add-to-menubar</span> <span class="s">"My menu"</span><span class="p">)</span>
<span class="p">(</span><span class="nv">menu-bar-open</span><span class="p">)</span>
</code></pre></div></div>

<p>Select any of those 3 items to learn that the numbers in the
<code class="language-plaintext highlighter-rouge">imenu--index-alist</code> alist are absolute buffer positions. Nice to know.</p>

<p>Notice that besides the 3 items you hard-codeed in
<code class="language-plaintext highlighter-rouge">imenu--index-alist</code> there is a 4th item <code class="language-plaintext highlighter-rouge">*Rescan*</code>. Selecting it will
restore the original Imenu items to the 2 <code class="language-plaintext highlighter-rouge">greet</code> and <code class="language-plaintext highlighter-rouge">be-kind</code>
functions.</p>

<p>Another experiment you can do is:</p>

<ul>
  <li>Evaluate again</li>
</ul>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">imenu--index-alist</span>
  <span class="o">`</span><span class="p">((</span><span class="s">"beginning"</span> <span class="o">.</span> <span class="mi">1</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"third char"</span> <span class="o">.</span> <span class="mi">3</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"fifth char"</span> <span class="o">.</span> <span class="mi">5</span><span class="p">)))</span>
</code></pre></div></div>

<ul>
  <li>Run <code class="language-plaintext highlighter-rouge">consult-imenu</code>.</li>
</ul>

<p>You will not see those 3 hard-coded items. Instead, it seems that
<code class="language-plaintext highlighter-rouge">consult-imenu</code> invokes <code class="language-plaintext highlighter-rouge">*Rescan*</code> when it starts.</p>

<p>Wrapping up, our first intuition could be that:</p>

<ul>
  <li>Imenu displays the content of <code class="language-plaintext highlighter-rouge">imenu--index-alist</code>.</li>
  <li><code class="language-plaintext highlighter-rouge">imenu--index-alist</code> is populated by some function which is invoked
when <code class="language-plaintext highlighter-rouge">*Rescan*</code> is selected.</li>
  <li><code class="language-plaintext highlighter-rouge">consult-imenu</code> refreshes the content of <code class="language-plaintext highlighter-rouge">imenu--index-alist</code> when
it starts.</li>
</ul>

<h2 id="imenu-scanning">Imenu scanning</h2>
<p>So, when you visit a buffer <code class="language-plaintext highlighter-rouge">imenu--index-alist</code> does not start empty:
it already contains some reasonable values. We can infer that some
function must have automatically run, that inserted the proper items.
If you reset <code class="language-plaintext highlighter-rouge">imenu--index-alist</code>:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(setq imenu--index-alist nil)
</code></pre></div></div>

<p>and you run again <code class="language-plaintext highlighter-rouge">imenu</code>, you can verify that <code class="language-plaintext highlighter-rouge">greet</code> and <code class="language-plaintext highlighter-rouge">be-kind</code>
are back: Imenu has rescaned the buffer and detected them.</p>

<p>Which function in Emacs populates <code class="language-plaintext highlighter-rouge">imenu--index-alist</code>?<br />
The answer is: it’s up to you. Imenu does not care, you can plug in
any function you like, as long as it returns an alist to use.</p>

<p>If you poke into the Imenu code, you will find this snippet as part
of the <code class="language-plaintext highlighter-rouge">imenu--make-index-alist</code> function:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">imenu--index-alist</span>
      <span class="o">...</span>
      <span class="o">...</span>
      <span class="p">(</span><span class="nb">funcall</span> <span class="nv">imenu-create-index-function</span><span class="p">))</span>
</code></pre></div></div>

<p>This! We spotted the code where <code class="language-plaintext highlighter-rouge">imenu--index-alist</code> is populated!<br />
So, Imenu expects that someone or something provides it with a
function to scan the buffer and to return an index of menu item. This
<em>something</em> is normally the major mode of the buffer.</p>

<p>To challenge this, let’s activate a major mode and let’s discover
which function <code class="language-plaintext highlighter-rouge">imenu-create-index-function</code> targets:</p>

<ul>
  <li>
    <p>Visit a Markdown file and run <code class="language-plaintext highlighter-rouge">M-x describe-variable RET
imenu-create-index-function</code>. It reveals that the function used by
Imenu is <code class="language-plaintext highlighter-rouge">markdown-imenu-create-nested-index</code>. Apparently, an
implementation very specific to Markdown.</p>
  </li>
  <li>
    <p>If you visit a C file, instead, the value of
<code class="language-plaintext highlighter-rouge">imenu-create-index-function</code> is
<code class="language-plaintext highlighter-rouge">imenu-default-create-index-function</code>, which sounds more generic.</p>
  </li>
  <li>
    <p>The same happens for a lot of other major modes.</p>
  </li>
</ul>

<p>So, interestingly: some major modes provide a custom way for scanning
their buffers and indexing the Imenu; others rely on a default
function, provided by Imenu itself.</p>

<p>This provides a hint about what a major mode is: a function providing
a collection of variable values. (If you want to know a bit more about
major modes, you might like <a href="/emacs-hooks">Emacs: how to activate the functionality
X for all files of type Y?</a>).</p>

<p>It also gives us some suggestions:</p>

<ul>
  <li>
    <p>Should not we find a better method, when developing the Tree-sitter
mode for F# we can always develop a completely custom Imenu index
function, and we can plug it into Imenu through
<code class="language-plaintext highlighter-rouge">imenu-create-index-function</code>.</p>
  </li>
  <li>
    <p>This <code class="language-plaintext highlighter-rouge">imenu-default-create-index-function</code> default implementation
sounds inspiring. It’s used by a variety of independent major modes,
therefore it must offer some flexible options to customize it. Let’s
investigate.</p>
  </li>
</ul>

<p>So, our next 2 goals to challenge our discovery can be:</p>

<ul>
  <li>We write a completely custom index function, and we plug it into
Imenu.</li>
  <li>Then, we study what the default Imenu index function offers.</li>
</ul>

<h2 id="a-custom-imenu-create-index-function">A custom imenu-create-index-function</h2>
<p>Open the scratch buffer (<code class="language-plaintext highlighter-rouge">M-x scratch-buffer RET</code>) and evaluate:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-index-function</span> <span class="p">()</span>
  <span class="o">'</span><span class="p">((</span><span class="s">"one"</span> <span class="o">.</span> <span class="mi">1</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"two"</span> <span class="o">.</span> <span class="mi">2</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"three"</span> <span class="o">.</span> <span class="mi">3</span><span class="p">)))</span>

<span class="p">(</span><span class="k">setq</span> <span class="nv">imenu-create-index-function</span> <span class="nf">#'</span><span class="nv">my-index-function</span><span class="p">)</span>
</code></pre></div></div>

<p>Then reopen <code class="language-plaintext highlighter-rouge">imenu</code> and rescan the index (or just use <code class="language-plaintext highlighter-rouge">consult-imenu</code>
which we learnt always rescans the index).<br />
Yes! We see the 3 items.</p>

<p>Of course, our function needn’t return hard-coded values; it can
contain any custom logic. It could generate an index in a cycle:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-index-function</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">cl-loop</span> <span class="nv">for</span> <span class="nv">i</span> <span class="nv">from</span> <span class="mi">1</span> <span class="nv">to</span> <span class="mi">50</span>
           <span class="nv">collect</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">format</span> <span class="s">"Item %d"</span> <span class="nv">i</span><span class="p">)</span> <span class="nv">i</span><span class="p">)))</span>
</code></pre></div></div>

<p>or it could actually scan the buffer searching for <code class="language-plaintext highlighter-rouge">(defun FUNCNAME</code>
patterns:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-index-function</span> <span class="p">()</span>
  <span class="p">(</span><span class="nv">save-excursion</span>
    <span class="p">(</span><span class="nv">goto-char</span> <span class="p">(</span><span class="nv">point-min</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">cl-loop</span> <span class="nv">while</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nv">eobp</span><span class="p">))</span>
             <span class="nv">for</span> <span class="nv">item</span> <span class="nb">=</span> <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nv">looking-at</span> <span class="s">"(defun\\s-+\\(\\S-+\\)"</span><span class="p">)</span>
                          <span class="o">`</span><span class="p">(</span><span class="o">,</span><span class="p">(</span><span class="nv">match-string</span> <span class="mi">1</span><span class="p">)</span> <span class="o">.</span> <span class="o">,</span><span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
             <span class="k">if</span> <span class="nv">item</span> <span class="nv">collect</span> <span class="nv">item</span>
             <span class="nb">do</span> <span class="p">(</span><span class="nv">forward-line</span> <span class="mi">1</span><span class="p">))))</span>
</code></pre></div></div>

<p>Cool. This gives up hope to integrate Imenu with Tree-sitter. We
could:</p>

<ul>
  <li>ask Tree-sitter to analyze the buffer and to return back the
syntax tree for our F# file.</li>
  <li>use some custom logic to scan the syntax tree — instead of the
chars in the buffer — building one item for each of the F#
structural elements we want to index.</li>
</ul>

<p>Way better than working with regular expressions. We will get to it.</p>

<h2 id="the-default-imenu-index-function">The default imenu index function</h2>
<p>Time to see what’s inside the default index function, provided
out-of-the-box by <code class="language-plaintext highlighter-rouge">imenu.el</code>.</p>

<ul>
  <li>Open the function documentation with <code class="language-plaintext highlighter-rouge">M-x describe-function RET
imenu-default-create-index-function RET</code>.</li>
  <li>Access its code with <code class="language-plaintext highlighter-rouge">M-x help-view-source RET</code> (or just type <code class="language-plaintext highlighter-rouge">s</code>).</li>
</ul>

<p>This reveals this implementation (for some reason, with a wrong
indentation), which is not too complicated:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">imenu-default-create-index-function</span> <span class="p">()</span>
  <span class="s">"Default function to create an index alist of the current buffer.

The most general method is to move point to end of buffer, then repeatedly call
`imenu-prev-index-position-function' and `imenu-extract-index-name-function'.
All the results returned by the latter are gathered into an index alist.
This method is used if those two variables are non-nil.

The alternate method, which is the one most often used, is to call
`imenu--generic-function' with `imenu-generic-expression' as argument."</span>
  <span class="c1">;; These should really be done by setting imenu-create-index-function</span>
  <span class="c1">;; in these major modes.  But save that change for later.</span>
  <span class="p">(</span><span class="nb">cond</span> <span class="p">((</span><span class="nb">and</span> <span class="nv">imenu-prev-index-position-function</span>
	      <span class="nv">imenu-extract-index-name-function</span><span class="p">)</span>
	 <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">index-alist</span> <span class="o">'</span><span class="p">())</span> <span class="p">(</span><span class="nv">pos</span> <span class="p">(</span><span class="nv">point-max</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">start</span> <span class="p">(</span><span class="nv">float-time</span><span class="p">))</span>
	       <span class="nv">name</span><span class="p">)</span>
	   <span class="p">(</span><span class="nv">goto-char</span> <span class="nv">pos</span><span class="p">)</span>
	   <span class="c1">;; Search for the function</span>
	   <span class="p">(</span><span class="nv">while</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">funcall</span> <span class="nv">imenu-prev-index-position-function</span><span class="p">)</span>
                       <span class="c1">;; Don't use an excessive amount of time.</span>
                       <span class="p">(</span><span class="nb">&lt;</span> <span class="p">(</span><span class="nb">-</span> <span class="p">(</span><span class="nv">float-time</span><span class="p">)</span> <span class="nv">start</span><span class="p">)</span> <span class="nv">imenu-max-index-time</span><span class="p">))</span>
             <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nb">&lt;</span> <span class="p">(</span><span class="nv">point</span><span class="p">)</span> <span class="nv">pos</span><span class="p">)</span>
               <span class="p">(</span><span class="nb">error</span> <span class="s">"Infinite loop at %s:%d: imenu-prev-index-position-function does not move point"</span> <span class="p">(</span><span class="nv">buffer-name</span><span class="p">)</span> <span class="nv">pos</span><span class="p">))</span>
             <span class="p">(</span><span class="k">setq</span> <span class="nv">pos</span> <span class="p">(</span><span class="nv">point</span><span class="p">))</span>
	     <span class="p">(</span><span class="nv">save-excursion</span>
	       <span class="p">(</span><span class="k">setq</span> <span class="nv">name</span> <span class="p">(</span><span class="nb">funcall</span> <span class="nv">imenu-extract-index-name-function</span><span class="p">)))</span>
	     <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">stringp</span> <span class="nv">name</span><span class="p">)</span>
 		  <span class="c1">;; [ydi] Updated for imenu-use-markers.</span>
		  <span class="p">(</span><span class="nb">push</span> <span class="p">(</span><span class="nb">cons</span> <span class="nv">name</span>
                              <span class="p">(</span><span class="k">if</span> <span class="nv">imenu-use-markers</span> <span class="p">(</span><span class="nv">point-marker</span><span class="p">)</span> <span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
			<span class="nv">index-alist</span><span class="p">)))</span>
	   <span class="nv">index-alist</span><span class="p">))</span>
	<span class="c1">;; Use generic expression if possible.</span>
	<span class="p">((</span><span class="nb">and</span> <span class="nv">imenu-generic-expression</span><span class="p">)</span>
	 <span class="p">(</span><span class="nv">imenu--generic-function</span> <span class="nv">imenu-generic-expression</span><span class="p">))</span>
	<span class="p">(</span><span class="no">t</span>
         <span class="p">(</span><span class="nv">imenu-unavailable-error</span> <span class="s">"This buffer cannot use `imenu-default-create-index-function'"</span><span class="p">))))</span>
</code></pre></div></div>

<p>Reduced to its core, it looks like the following:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">imenu-default-create-index-function</span> <span class="p">()</span>
  <span class="p">(</span><span class="nb">cond</span> <span class="p">((</span><span class="nb">and</span> <span class="nv">imenu-prev-index-position-function</span>
	          <span class="nv">imenu-extract-index-name-function</span><span class="p">)</span>
	          
              <span class="c1">;; [code omitted]</span>
              <span class="c1">;; index using those 2 functions</span>

	    <span class="p">((</span><span class="nb">and</span> <span class="nv">imenu-generic-expression</span><span class="p">)</span>
	     <span class="p">(</span><span class="nv">imenu--generic-function</span> <span class="nv">imenu-generic-expression</span><span class="p">))</span>
	    <span class="p">(</span><span class="no">t</span>
         <span class="p">(</span><span class="nv">imenu-unavailable-error</span> <span class="s">"This buffer cannot use `imenu-default-create-index-function'"</span><span class="p">))))</span>
</code></pre></div></div>

<p>Basically:</p>

<ol>
  <li>It checks if the major mode provides 2 specific functions for
  indexing (one for positioning, one for extracting). If so, it uses
  them. We will see how this work in a minute.</li>
  <li>Otherwise, it checks if the major mode provides a set of regular
  expressions (in the variable <code class="language-plaintext highlighter-rouge">imenu-generic-expression</code>). If so, it
  uses them, delegating the work to the function
  <code class="language-plaintext highlighter-rouge">imenu--generic-function</code>.</li>
  <li>Otherwise, it raises an error.</li>
</ol>

<p>Let’s start from the case 2, which is by far and large the most
popular — but not necessarily the most powerful — usage of
Imenu.</p>

<h3 id="imenu-generic-expression">imenu-generic-expression</h3>
<p>So, this is the case in which <code class="language-plaintext highlighter-rouge">imenu--generic-function</code> is passed the
regular expressions defined in <code class="language-plaintext highlighter-rouge">imenu-generic-expression</code>. I’m curious
to inspect both. Notice that <code class="language-plaintext highlighter-rouge">imenu--generic-function</code> is private, so
it’s not meant to be modified. <code class="language-plaintext highlighter-rouge">imenu-generic-expression</code>, instead, is
meant to be customized.</p>

<p>If you visit the scratch buffer and you inspect the value of
<code class="language-plaintext highlighter-rouge">imenu-generic-expression</code> you will find a collection of very well
crafted regular expressions:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="p">((</span><span class="no">nil</span> <span class="s">"^\\s-*(\\(cl-def\\(?:generic\\|ine-compiler-macro\\|m\\(?:acro\\|ethod\\)\\|subst\\|un\\)\\|def\\(?:advice\\|generic\\|ine-\\(?:advice\\|compil\\(?:ation-mode\\|er-macro\\)\\|derived-mode\\|g\\(?:\\(?:eneric\\|lobal\\(?:\\(?:ized\\)?-minor\\)\\)-mode\\)\\|inline\\|m\\(?:ethod-combination\\|inor-mode\\|odify-macro\\)\\|s\\(?:etf-expander\\|keleton\\)\\)\\|m\\(?:acro\\|ethod\\)\\|s\\(?:etf\\|ubst\\)\\|un\\*?\\)\\|ert-deftest\\)\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)"</span> <span class="mi">2</span><span class="p">)</span>
   <span class="p">(</span><span class="no">nil</span> <span class="s">"^\\s-*(\\(def\\(?:\\(?:ine-obsolete-function-\\)?alias\\)\\)\\s-+'\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)"</span> <span class="mi">2</span><span class="p">)</span>
   <span class="p">(</span><span class="s">"Variables"</span> <span class="s">"^\\s-*(\\(def\\(?:c\\(?:onst\\(?:ant\\)?\\|ustom\\)\\|ine-symbol-macro\\|parameter\\)\\)\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)"</span> <span class="mi">2</span><span class="p">)</span>
   <span class="p">(</span><span class="s">"Variables"</span> <span class="s">"^\\s-*(defvar\\(?:-local\\)?\\s-+\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)[[:space:]
  ]+[^)]"</span> <span class="mi">1</span><span class="p">)</span>
   <span class="p">(</span><span class="s">"Types"</span> <span class="s">"^\\s-*(\\(cl-def\\(?:struct\\|type\\)\\|def\\(?:class\\|face\\|group\\|ine-\\(?:condition\\|error\\|widget\\)\\|package\\|struct\\|t\\(?:\\(?:hem\\|yp\\)e\\)\\)\\)\\s-+'?\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)+\\)"</span> <span class="mi">2</span><span class="p">))</span>
</code></pre></div></div>

<p>I don’t even dare an attempt to understand. I’m just too grateful to
whoever took the time to write them. Chapeau!<br />
I am more interested in answering the questions:</p>

<ul>
  <li>In which file of Emacs is this value defined?</li>
  <li>How is this used by Imenu? What does <code class="language-plaintext highlighter-rouge">imenu--generic-function</code> do
with this collecgtion?</li>
</ul>

<p>To answer the first question, we can follow our intuition: it’s up to
the major mode to configure Imenu. So, we can:</p>

<ul>
  <li>Inspect which major mode is used by the current buffer, with <code class="language-plaintext highlighter-rouge">M-x
describe-mode</code>.</li>
  <li>Navigate to its source code, from the file link mentioned in the
documentation.</li>
  <li>Search for a reference to <code class="language-plaintext highlighter-rouge">(setq-local imenu-generic-expression</code>.</li>
  <li>If no result is found, we navigate to the parent major mode,
following the expressions like <code class="language-plaintext highlighter-rouge">(define-derived-mode current-mode
parent-mode</code> hitting <code class="language-plaintext highlighter-rouge">M-.</code> on <code class="language-plaintext highlighter-rouge">parent-mode</code> (again, read the <a href="/emacs-hooks">post
about hooks</a> to learn more).</li>
</ul>

<p>Doing this exercise starting from the scratch buffer takes us to the
file <code class="language-plaintext highlighter-rouge">lisp-mode.el</code> where a giant variable
<code class="language-plaintext highlighter-rouge">lisp-imenu-generic-expression</code> is defined:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defvar</span> <span class="nv">lisp-imenu-generic-expression</span>
  <span class="p">(</span><span class="nb">list</span>
   <span class="p">(</span><span class="nb">list</span> <span class="no">nil</span>
	 <span class="p">(</span><span class="nv">purecopy</span> <span class="p">(</span><span class="nv">concat</span> <span class="s">"^\\s-*("</span>
			   <span class="p">(</span><span class="nv">regexp-opt</span>
			    <span class="o">'</span><span class="p">(</span><span class="s">"defun"</span> <span class="s">"defmacro"</span>
                              <span class="c1">;; Elisp.</span>
                              <span class="s">"defun*"</span> <span class="s">"defsubst"</span> <span class="s">"define-inline"</span>
			      <span class="s">"define-advice"</span> <span class="s">"defadvice"</span> <span class="s">"define-skeleton"</span>
			      <span class="s">"define-compilation-mode"</span> <span class="s">"define-minor-mode"</span>
			      <span class="s">"define-global-minor-mode"</span>
			      <span class="s">"define-globalized-minor-mode"</span>
  <span class="o">...</span>
  <span class="c1">;; [code omitted]</span>
</code></pre></div></div>

<p>Mystery solved.</p>

<p>Now, we just need to understand how this collection of regular
expressions is used. If you remember, the default implementation of
the index function <code class="language-plaintext highlighter-rouge">imenu-default-create-index-function</code> mentioned:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>	    ((and imenu-generic-expression)
	     (imenu--generic-function imenu-generic-expression))
</code></pre></div></div>

<p>Let’s give a look to the code of <code class="language-plaintext highlighter-rouge">imenu--generic-function</code>:</p>

<ul>
  <li>Do a <code class="language-plaintext highlighter-rouge">M-x describe-function RET imenu--generic-function RET</code>.</li>
  <li>Then <code class="language-plaintext highlighter-rouge">M-x help-view-source</code> (or just hit <code class="language-plaintext highlighter-rouge">s</code>).</li>
</ul>

<p>Phew! This one is way more complex than the one before. What is
relevant for us is:</p>

<ul>
  <li>
    <p>It maps over the elements of <code class="language-plaintext highlighter-rouge">imenu-generic-expression</code>, the
collection of regexen. We expected that.</p>
  </li>
  <li>
    <p>For each regex, it starts with a <code class="language-plaintext highlighter-rouge">(goto-char (point-max))</code>. This
means, it scans the buffer backwards, allegedly “for convenience of
adding items in order”.</p>
  </li>
  <li>
    <p>Then, it collectes each matching candidate.</p>
  </li>
</ul>

<p>OK, not too alien. The reason why the function is so long is because
it also takes into account error handling, duplicates, execution time,
edge cases etc. We can skate over it.</p>

<p>Instead, let’s put it into play. Type in the scratch buffer:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">-</span> <span class="nv">buy</span> <span class="nv">apples</span>
<span class="nb">-</span> <span class="nv">buy</span> <span class="nv">bananas</span>
<span class="nb">-</span> <span class="nv">sell</span> <span class="nv">ananas</span>

<span class="p">(</span><span class="nv">setq-local</span> <span class="nv">imenu-create-index-function</span> <span class="nf">#'</span><span class="nv">imenu-default-create-index-function</span><span class="p">)</span>

<span class="p">(</span><span class="k">setq</span> <span class="nv">imenu-generic-expression</span>
  <span class="o">'</span><span class="p">((</span><span class="s">"to buy"</span> <span class="s">"^- buy \\(.*\\)$"</span> <span class="mi">1</span><span class="p">)</span>
    <span class="p">(</span><span class="s">"to sell"</span> <span class="s">"^- sell \\(.*\\)$"</span> <span class="mi">1</span><span class="p">)))</span>
</code></pre></div></div>

<p>Each element in the <code class="language-plaintext highlighter-rouge">imenu-generic-expression</code> shall follow this
pattern:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">MENU-TITLE</span> <span class="nv">REGEXP</span> <span class="nv">INDEX</span><span class="p">)</span>
</code></pre></div></div>

<p>where</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">MENU-TITLE</code> is the title of the submenu to host the item.</li>
  <li><code class="language-plaintext highlighter-rouge">REGEXP</code> is the regular expression to capture the candidate. The
regex may contain a group.</li>
  <li><code class="language-plaintext highlighter-rouge">INDEX</code> is the group number to use as the item to be displayed. <code class="language-plaintext highlighter-rouge">0</code>
means the whole match.</li>
</ul>

<p>There are other options, which you can consult visiting <code class="language-plaintext highlighter-rouge">M-x
describe-variable RET imenu-generic-expression RET</code>.</p>

<p>We will not deepen this approach any further: we know that the F#
major mode will rely on the syntax tree provided by Tree-sitter, not
on regular expressions.</p>

<p>Let’s see, instead, the other option offered by the default index
function, <code class="language-plaintext highlighter-rouge">imenu-default-create-index-function</code>.</p>

<h2 id="find-position-and-extract">Find position and extract</h2>
<p>Remember that we summarized <code class="language-plaintext highlighter-rouge">imenu-default-create-index-function</code> as:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">imenu-default-create-index-function</span> <span class="p">()</span>
  <span class="p">(</span><span class="nb">cond</span> <span class="p">((</span><span class="nb">and</span> <span class="nv">imenu-prev-index-position-function</span>
	          <span class="nv">imenu-extract-index-name-function</span><span class="p">)</span>
	          
              <span class="c1">;; [code omitted]</span>
              <span class="c1">;; index using those 2 functions</span>

	    <span class="p">((</span><span class="nb">and</span> <span class="nv">imenu-generic-expression</span><span class="p">)</span>
	     <span class="p">(</span><span class="nv">imenu--generic-function</span> <span class="nv">imenu-generic-expression</span><span class="p">))</span>
	    <span class="p">(</span><span class="no">t</span>
         <span class="p">(</span><span class="nv">imenu-unavailable-error</span> <span class="s">"This buffer cannot use `imenu-default-create-index-function'"</span><span class="p">))))</span>
</code></pre></div></div>

<p>and that we said that the first branch of the condition:</p>

<ul>
  <li>uses a combination of 2 functions,
<code class="language-plaintext highlighter-rouge">imenu-prev-index-position-function</code> and
<code class="language-plaintext highlighter-rouge">imenu-extract-index-name-function</code>. The former finds the position
of the next candidate; the latter builds the index item for that
candidate.</li>
</ul>

<p>It’s time to say more about what the omitted code does. It was:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">index-alist</span> <span class="o">'</span><span class="p">())</span> <span class="p">(</span><span class="nv">pos</span> <span class="p">(</span><span class="nv">point-max</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">start</span> <span class="p">(</span><span class="nv">float-time</span><span class="p">))</span>
	  <span class="nv">name</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">goto-char</span> <span class="nv">pos</span><span class="p">)</span>
  <span class="c1">;; Search for the function</span>
  <span class="p">(</span><span class="nv">while</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">funcall</span> <span class="nv">imenu-prev-index-position-function</span><span class="p">)</span>
              <span class="c1">;; Don't use an excessive amount of time.</span>
              <span class="p">(</span><span class="nb">&lt;</span> <span class="p">(</span><span class="nb">-</span> <span class="p">(</span><span class="nv">float-time</span><span class="p">)</span> <span class="nv">start</span><span class="p">)</span> <span class="nv">imenu-max-index-time</span><span class="p">))</span>
    <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nb">&lt;</span> <span class="p">(</span><span class="nv">point</span><span class="p">)</span> <span class="nv">pos</span><span class="p">)</span>
      <span class="p">(</span><span class="nb">error</span> <span class="s">"Infinite loop at %s:%d: imenu-prev-index-position-function does not move point"</span> <span class="p">(</span><span class="nv">buffer-name</span><span class="p">)</span> <span class="nv">pos</span><span class="p">))</span>
    <span class="p">(</span><span class="k">setq</span> <span class="nv">pos</span> <span class="p">(</span><span class="nv">point</span><span class="p">))</span>
	<span class="p">(</span><span class="nv">save-excursion</span>
	  <span class="p">(</span><span class="k">setq</span> <span class="nv">name</span> <span class="p">(</span><span class="nb">funcall</span> <span class="nv">imenu-extract-index-name-function</span><span class="p">)))</span>
	<span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">stringp</span> <span class="nv">name</span><span class="p">)</span>
 		 <span class="c1">;; [ydi] Updated for imenu-use-markers.</span>
		 <span class="p">(</span><span class="nb">push</span> <span class="p">(</span><span class="nb">cons</span> <span class="nv">name</span>
                     <span class="p">(</span><span class="k">if</span> <span class="nv">imenu-use-markers</span> <span class="p">(</span><span class="nv">point-marker</span><span class="p">)</span> <span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
			   <span class="nv">index-alist</span><span class="p">)))</span>
  <span class="nv">index-alist</span><span class="p">)</span>
</code></pre></div></div>

<p>Indulge me while to simplify it in this naïve way:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">index-alist</span> <span class="o">'</span><span class="p">())</span>
      <span class="p">(</span><span class="nv">pos</span> <span class="p">(</span><span class="nv">point-max</span><span class="p">))</span>
      <span class="p">(</span><span class="nv">name</span> <span class="no">nil</span><span class="p">))</span>
  
  <span class="p">(</span><span class="nv">goto-char</span> <span class="nv">pos</span><span class="p">)</span>

  <span class="p">(</span><span class="nv">while</span> <span class="p">(</span><span class="nb">funcall</span> <span class="nv">imenu-prev-index-position-function</span><span class="p">)</span>
    <span class="p">(</span><span class="k">setq</span> <span class="nv">pos</span> <span class="p">(</span><span class="nv">point</span><span class="p">))</span>
	<span class="p">(</span><span class="nv">save-excursion</span>
	  <span class="p">(</span><span class="k">setq</span> <span class="nv">name</span> <span class="p">(</span><span class="nb">funcall</span> <span class="nv">imenu-extract-index-name-function</span><span class="p">)))</span>
	<span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">stringp</span> <span class="nv">name</span><span class="p">)</span>
		 <span class="p">(</span><span class="nb">push</span> <span class="p">(</span><span class="nb">cons</span> <span class="nv">name</span> <span class="p">(</span><span class="nv">point</span><span class="p">))</span>
			   <span class="nv">index-alist</span><span class="p">)))</span>
  <span class="nv">index-alist</span><span class="p">)</span>
</code></pre></div></div>

<p>We can interpret it as:</p>

<ul>
  <li>It starts from the end. As before, then, it scans the buffer
backward.</li>
  <li>As long as it finds candidates, it runs a cycle.</li>
  <li>For each step of the cycle it makes use of 2 custom functions:
    <ul>
      <li><code class="language-plaintext highlighter-rouge">imenu-prev-index-position-function</code>, which has the goal of
finding a candidate and moving the point there.</li>
      <li><code class="language-plaintext highlighter-rouge">imenu-extract-index-name-function</code> which, given the found
candidate, has the goal to calculate the menu item.</li>
    </ul>
  </li>
  <li>When it’s done, it returns the collection of items.</li>
</ul>

<p>OK, fair enough. Let’s give it a shot with a silly example which
creates a menu item for each line in the buffer:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">find-all-lines</span> <span class="p">()</span>
  <span class="s">"Move point to previous lines, returning t each time.
Returns nil when reaching buffer start, signaling completion."</span>
  <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">=</span> <span class="p">(</span><span class="nv">point</span><span class="p">)</span> <span class="p">(</span><span class="nv">point-min</span><span class="p">))</span>
      <span class="no">nil</span>
    <span class="p">(</span><span class="nv">forward-line</span> <span class="mi">-1</span><span class="p">)</span>
    <span class="no">t</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">get-line-number</span> <span class="p">()</span>
  <span class="s">"Return the current line number as the index name."</span>
  <span class="p">(</span><span class="nb">format</span> <span class="s">"Line %d"</span> <span class="p">(</span><span class="nv">line-number-at-pos</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">setq-local</span> <span class="nv">imenu-prev-index-position-function</span> <span class="nf">#'</span><span class="nv">find-all-lines</span><span class="p">)</span>
<span class="p">(</span><span class="nv">setq-local</span> <span class="nv">imenu-extract-index-name-function</span> <span class="nf">#'</span><span class="nv">get-line-number</span><span class="p">)</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">find-all-lines</code> always indicates that the beginning of each line is
a good candidate.</li>
  <li>Given the start of line position, <code class="language-plaintext highlighter-rouge">get-line-number</code> just returns a
string with the line number as the menu item name to display.</li>
</ul>

<p>Run it with <code class="language-plaintext highlighter-rouge">imenu</code>. Nice, it works.
vvv</p>
<h2 id="what-about-tree-sitter">What about Tree-sitter?</h2>
<p>So, which approach shall we take to integrate imenu with Tree-sitter?
Sure enough, we won’t rely on <code class="language-plaintext highlighter-rouge">imenu-generic-expression</code> and its
regular expressions. Shall we play with the couple of position+extract
functions? Or will we have to develop a whole brand new custom index
function to replace the standard
<code class="language-plaintext highlighter-rouge">imenu-default-create-index-function</code>?</p>

<p>It turns out <code class="language-plaintext highlighter-rouge">treesit</code>, the built-in Tree-sitter package, has some
delightful surprises for us. But this is the topic for the next
episode.</p>

<p>Hang tight! Happy emacsing.</p>

<p>(Thank you <a href="https://protesilaos.com/coach/">Prot</a> for guiding me in this journey)</p>

<h1 id="references">References</h1>

<ul>
  <li><a href="https://github.com/minad/consult">consult.el</a></li>
  <li><a href="/emacs-hooks">Emacs: how to activate the functionality X for all files of type Y?</a></li>
  <li><a href="https://protesilaos.com/coach/">Protesilaos Stavrou</a></li>
</ul>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="emacs" /><category term="lisp" /><summary type="html"><![CDATA[I promised myself to write a Tree-sitter major mode for F#. I’ve been told that it should not be such an insurmountable endeavour, but given that I start from the scratch, along the journey I will need to learn a bunch of new topics from the ground up. Nice, that’s why we use Emacs, right? For each of those themes, I will publish a little blog post to share the lesson learnt. Today it’s the Imenu’s turn.]]></summary></entry><entry><title type="html">I suck at TDD (and how to fix it) - Review</title><link href="http://arialdomartini.github.io/diamond-review" rel="alternate" type="text/html" title="I suck at TDD (and how to fix it) - Review" /><published>2024-11-24T00:00:00+00:00</published><updated>2024-11-24T00:00:00+00:00</updated><id>http://arialdomartini.github.io/diamond-review</id><content type="html" xml:base="http://arialdomartini.github.io/diamond-review"><![CDATA[<h2 id="summaries">Summaries</h2>

<p>From Matteo Vaccari:</p>

<p>There’s no easy way to evolve the hardcoded values into general code.</p>

<ul>
  <li>Alistair Cockburn said that this problem could be better solved by
more mathematically-oriented thinking upfront about how many spaces
should be generated where</li>
  <li>Emily Bache said that “recycling tests” is a valid way to iterate
towards a difficult problem</li>
  <li>Other solutions came from Ron Jeffries, George Dinwiddie, Jon
Jagger, again Ron Jeffries</li>
</ul>

<h3 id="francesco-cirillo">Francesco Cirillo</h3>
<p><a href="https://www.antiifprogramming.com/anti-if-workshop-the-diamond-kata.php">Francesco Cirillo - The Diamond Kata  Anti-IF Workshop</a></p>

<ul>
  <li>Payed workshop.</li>
  <li>It promises that TDD and Anti-IF Programming “let design
abstractions emerge […] in a way that prioritizes intentional
design over algorithmic complexity, allowing for an adaptable and
emergent solution.”</li>
  <li>It states: “No Thinking Ahead Required: Unlike conventional wisdom,
this workshop will show you how to solve the Diamond Kata using TDD
without the need for anticipatory thinking […] showing how
abstractions emerge naturally through TDD.”</li>
</ul>

<h3 id="seb-rose">Seb Rose</h3>
<p><a href="https://claysnow.co.uk/recycling-tests-in-tdd/">Seb Rose - Recycling tests in TDD</a></p>

<ul>
  <li>Seb uses the Print Diamond Kata in his trainings.</li>
  <li>He relies on the classical test progression (first the <code class="language-plaintext highlighter-rouge">a</code> case,
then the <code class="language-plaintext highlighter-rouge">b</code> case, etc).</li>
  <li>He shows how some implementations are hardcoded (applying Fake It
Until You Make It).</li>
  <li>He mentions the typical struggle with Example-Based TDD: “The code
is now screaming for us to refactor it, but to keep all the tests
passing most people try to solve the entire problem at once. That’s
hard, because we’ll need to cope with multiple lines, varying
indentation, and repeated characters with a varying number of spaces
between them.”</li>
  <li>He suggests a second approach: “we start by decomposing the diamond
problem into smaller constituent parts. This time I chose to write
the following test:”</li>
  <li>He mentions the “the top half of the diamond”, without making it
explicit it the code.</li>
  <li>He claims that “by recycling the second test multiple times, each
time modifying the expected output to become closer to what we
actual want, we’ve allowed ourselves to be guided gradually to a
solution.”</li>
</ul>

<p>Here are the used tests:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">TestFixture</span><span class="p">]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">DiamondTest</span>
<span class="p">{</span>
    <span class="p">[</span><span class="n">Test</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">A_should_generate_a_single_character</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">"A"</span><span class="p">,</span> <span class="n">Diamond</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="sc">'A'</span><span class="p">));</span>
    <span class="p">}</span>
 
    <span class="p">[</span><span class="n">Test</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">B_should_generate_the_smallest_diamond</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">" A\nB B\n A"</span><span class="p">,</span> <span class="n">Diamond</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="sc">'B'</span><span class="p">));</span>
    <span class="p">}</span>
 
    <span class="p">[</span><span class="n">Test</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">C_should_generate_the_next_diamond</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">"  A\n B B\nC   C\n B B\n  A"</span><span class="p">,</span> <span class="n">Diamond</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="sc">'C'</span><span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p>and:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">using</span> <span class="nn">NUnit.Framework</span><span class="p">;</span>
 
<span class="p">[</span><span class="n">TestFixture</span><span class="p">]</span>
<span class="k">public</span> <span class="k">class</span> <span class="nc">DiamondTest</span>
<span class="p">{</span>
    <span class="p">[</span><span class="n">Test</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">A_should_give_single_character</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">"A\n"</span><span class="p">,</span> <span class="n">Diamond</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="sc">'A'</span><span class="p">));</span>
    <span class="p">}</span>
 
    <span class="p">[</span><span class="n">Test</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">B_should_be_a_diamond</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">" A\nB B\n A\n"</span><span class="p">,</span> <span class="n">Diamond</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="sc">'B'</span><span class="p">));</span>
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="s">" A\n"</span>  <span class="p">+</span>
                        <span class="s">"B B\n"</span> <span class="p">+</span> 
                        <span class="s">" A\n"</span><span class="p">,</span> <span class="n">Diamond</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="sc">'B'</span><span class="p">));</span>
    <span class="p">}</span>
 
    <span class="p">[</span><span class="n">Test</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">C_should_be_a_bigger_diamond</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="kt">string</span> <span class="n">diamond</span> <span class="p">=</span> <span class="s">"  A\n"</span>   <span class="p">+</span> 
                         <span class="s">" B B\n"</span>  <span class="p">+</span>
                         <span class="s">"C   C\n"</span> <span class="p">+</span>
                         <span class="s">" B B\n"</span>  <span class="p">+</span>
                         <span class="s">"  A\n"</span><span class="p">;</span>
 
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="n">diamond</span><span class="p">,</span> <span class="n">Diamond</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="sc">'C'</span><span class="p">));</span>
    <span class="p">}</span>
 
    <span class="p">[</span><span class="n">Test</span><span class="p">]</span>
    <span class="k">public</span> <span class="k">void</span> <span class="nf">D_should_be_an_even_bigger_diamond</span><span class="p">()</span>
    <span class="p">{</span>
        <span class="kt">string</span> <span class="n">diamond</span> <span class="p">=</span> <span class="s">"   A\n"</span>   <span class="p">+</span> 
                         <span class="s">"  B B\n"</span>  <span class="p">+</span>
                         <span class="s">" C   C\n"</span> <span class="p">+</span>
                         <span class="s">"D     D\n"</span> <span class="p">+</span>
                         <span class="s">" C   C\n"</span> <span class="p">+</span>
                         <span class="s">"  B B\n"</span>  <span class="p">+</span>
                         <span class="s">"   A\n"</span><span class="p">;</span>
 
        <span class="n">Assert</span><span class="p">.</span><span class="nf">AreEqual</span><span class="p">(</span><span class="n">diamond</span><span class="p">,</span> <span class="n">Diamond</span><span class="p">.</span><span class="nf">Create</span><span class="p">(</span><span class="sc">'D'</span><span class="p">));</span>
    <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><a href="https://claysnow.co.uk/diamond-recycling-and-painting-yourself-into-a-corner/">Seb Rose - Diamond recycling (and painting yourself into a
corner)</a></p>

<h3 id="alistair-cockburn">Alistair Cockburn</h3>
<p><a href="https://web.archive.org/web/20170621004437/http://alistair.cockburn.us/Thinking+before+programming">Alistair Cockburn - Thinking before programming</a></p>

<ul>
  <li>“[…] a few professors had the idea that they might teach
programmers to think a bit before hitting the keycaps. […]. They
showed how to create programs (of a certain category) without error,
by thinking about the properties of the problem and deriving the
program as a small exercise in simple logic.”</li>
  <li>Accorging to Alistair XP and TDD “when practiced well, involve a
different kind of thinking – not about the problem, but about the
code. TDD has become a pablum to avoid thinking.”</li>
  <li>His approach is to combine the Dijkstra-Gries approach (thinking
ahead) with TDD (“modern fine-grained incremental development”).</li>
  <li>In his premises, he seems to describe PBT: “What happens if we think
about the problem and look for patterns and properties before
starting, and then instead of typing the whole thing in at once, we
“grow” the program using fine-grained incremental development and
TDD?”</li>
  <li>Mentions the struggles about incremental development with TDD:</li>
</ul>

<blockquote>
  <p>Step 1: Go out and buy really good sneakers.</p>

  <p>Step 2: Do warmup exercises.</p>

  <p>Step 3: Jump really really really high, like, to the moon. “</p>
</blockquote>

<ul>
  <li>He promises to reflect on the problem, not on the solution.</li>
  <li>He identifies some properties:
    <ul>
      <li>The diamond is <code class="language-plaintext highlighter-rouge">2x+1</code> per <code class="language-plaintext highlighter-rouge">2x+1</code>.</li>
      <li>For each row, there are <code class="language-plaintext highlighter-rouge">2x-1</code> spacers.</li>
      <li>There is a formula for leading and trailing spaces.</li>
    </ul>
  </li>
  <li>Yet, he implements those ideas following the classical steps (case
<code class="language-plaintext highlighter-rouge">0</code>, then <code class="language-plaintext highlighter-rouge">1</code> etc).</li>
  <li>The formulas he conceived are the implementation. So, the test did
not guide the design, to the point that he writes the implementation
before the first test.</li>
  <li>Interestingly, the name of his tests have the typical “ForAll” form
of a property test:</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>def test_02_makes_and_fills_tray_of_any_size
</code></pre></div></div>

<ul>
  <li>
    <p>He claims that he did not type in all those tests at once, because
“to do so is not only against the rules of TDD […]), but is
actually dangerous”. I don’t agree with this: in fact, his
implementation (the fomula he conceived) was already complete. The
additional tests did not help evolving the formula.</p>
  </li>
  <li>
    <p>Even more interestingly, despite the initial good intuitions, his
tests are a description of the solution, not the problem:</p>
  </li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>:test_01_fills_first_and_last_slot_in_tray
:test_02_makes_and_fills_tray_of_any_size
:test_03_makes_bumper_for_row_in_diamond
:test_04_glues_bumpers_to_tray_making_complete_row_in_diamond
:test_05_makes_diamond_the_right_size
:test_06_puts_a_row_in_both_upper_and_lower_half_of_diamond
:test_07_digit_diamond_fills_correctly
</code></pre></div></div>

<ul>
  <li>Notice the use of expressions like “the right size” and “fills
correctly”.</li>
</ul>

<h3 id="jon-jagger">Jon Jagger</h3>
<p><a href="https://jonjagger.blogspot.com/2012/06/sliming-and-refactoring-and-deliberate.html">Jon Jagger - sliming and refactoring and deliberate duplication</a></p>

<ul>
  <li>Classic progression: <code class="language-plaintext highlighter-rouge">a</code> case, <code class="language-plaintext highlighter-rouge">b</code> case, <code class="language-plaintext highlighter-rouge">c</code> case, all hardcoded.</li>
  <li>He claims “As the tests get more specific, the code should get more
generic. I have three specific tests, but the code is equally
specific.”</li>
  <li>Beautful recursive implementation. Really brilliant.</li>
  <li>Yet, not induced by a test. Definitely, not an emergent design.</li>
</ul>

<h3 id="george-dinwiddie">George Dinwiddie</h3>
<p><a href="https://blog.gdinwiddie.com/2014/11/30/another-approach-to-the-diamond-kata/">George Dinwiddie -  Another Approach to the Diamond Kata</a></p>

<ul>
  <li>He also starts from the trivial degenerate diamond (with a hardcoded
implementation).</li>
  <li>“The next step is obviously to implement the <code class="language-plaintext highlighter-rouge">B</code> case”. Why
“obviously”?</li>
  <li>He refuses to hardcode <code class="language-plaintext highlighter-rouge">B</code>. His implementation, though, is not the
minumum code strictly necessary to make the test pass, but already a
generalization.</li>
</ul>

<h3 id="emily-bache">Emily Bache</h3>
<p><a href="https://coding-is-like-cooking.info/2015/04/iterative-incremental-tdd-diamond-kata/">Emily Bache - Iterative and Incremental TDD with the Diamond Kata</a></p>

<ul>
  <li>She believes that “recycling tests” is a valid way to iterate
towards a difficult problem</li>
  <li>Nothing new in her <a href="https://github.com/emilybache/DiamondKata">proposed repo</a>, though: tests
are incrementally going from <code class="language-plaintext highlighter-rouge">A</code> to <code class="language-plaintext highlighter-rouge">D</code>.</li>
</ul>

<h3 id="matteo-vaccari">Matteo Vaccari</h3>
<p><a href="https://matteo.vaccari.name/posts/the-diamond-kata-revisited/">Matteo Vaccari - The Diamond Kata Revisited</a></p>

<ul>
  <li>He acknowledges that “the problem statement is simple, but solving
it with TDD is not straightforward” because “there’s no easy way to
evolve the hardcoded values into general code”.</li>
  <li>Rather than trying to arrive at a “single algorithm” that will solve
the problem in one shot, he suggests a compositional approach.</li>
  <li>He analyzes some traits of the problem (not the solution!),
decomposing the problem into sub-problems and in fact capturing some
properties, such as the symmetry of quadrants.</li>
</ul>

<h3 id="géza-mihala">Géza Mihala</h3>
<p><a href="https://infinitary.org/stray_words/diamond_kata.html">Géza Mihala - Diamond Kata</a></p>

<ul>
  <li>Similarly to Matteo Vaccari, he plays with decomposing the problem
(using functional decomposition).</li>
  <li>He also identifies 2 properties: horizontal and vertical symmetry.</li>
  <li>The 4 properties that define the problem are:
    <ul>
      <li>a sequence of letters from ’A’ up to a given letter</li>
      <li>arranged diagonally in a square, padded with blanks</li>
      <li>mirrored to the left, not repeating the first column</li>
      <li>mirrored down, not repeating the bottom row</li>
    </ul>
  </li>
  <li>The only missing step in his post is: he does not use TDD at all.</li>
</ul>

<h1 id="references">References</h1>

<ul>
  <li>Resolved with Example-Based Testing
    <ul>
      <li><a href="https://www.antiifprogramming.com/anti-if-workshop-the-diamond-kata.php">Francesco Cirillo - The Diamond Kata  Anti-IF Workshop</a></li>
      <li><a href="https://claysnow.co.uk/recycling-tests-in-tdd/">Seb Rose - Recycling tests in TDD</a></li>
      <li><a href="https://claysnow.co.uk/diamond-recycling-and-painting-yourself-into-a-corner/">Seb Rose - Diamond recycling (and painting yourself into a corner)</a></li>
      <li><a href="https://web.archive.org/web/20170621004437/http://alistair.cockburn.us/Thinking+before+programming">Alistair Cockburn - Thinking before programming</a></li>
      <li><a href="https://jonjagger.blogspot.com/2012/06/sliming-and-refactoring-and-deliberate.html">Jon Jagger - sliming and refactoring and deliberate duplication</a></li>
      <li><a href="https://blog.gdinwiddie.com/2014/11/30/another-approach-to-the-diamond-kata/">George Dinwiddie -  Another Approach to the Diamond Kata</a></li>
      <li><a href="https://coding-is-like-cooking.info/2015/04/iterative-incremental-tdd-diamond-kata/">Emily Bache - Iterative and Incremental TDD with the Diamond Kata</a></li>
      <li><a href="https://github.com/emilybache/DiamondKata">Emily Bache - DiamondKata repository</a></li>
      <li><a href="https://matteo.vaccari.name/posts/the-diamond-kata-revisited/">Matteo Vaccari - The Diamond Kata Revisited</a></li>
      <li><a href="https://ronjeffries.com/articles/tdd-diamond/">Ron Jeffries - TDD on the Diamond Problem</a></li>
      <li><a href="https://ronjeffries.com/articles/more-diamond/">Ron Jeffries - More about Diamond</a></li>
      <li><a href="https://infinitary.org/stray_words/diamond_kata.html">Géza Mihala - Diamond Kata</a></li>
    </ul>
  </li>
  <li>Resolved with Property-Based Testing
    <ul>
      <li><a href="https://semaphoreci.com/community/tutorials/diamond-kata-tdd-with-only-property-based-tests">Nat Pryce - Diamond Kata – TDD with only Property-Based Tests</a></li>
      <li><a href="https://blog.ploeh.dk/2015/01/10/diamond-kata-with-fscheck/">Mark Seemann - Diamond kata with FsCheck</a></li>
      <li><a href="property based testing in javascript - diamond kata">Uldis Sturms - property based testing in javascript - diamond kata</a></li>
    </ul>
  </li>
</ul>

<h2>Functional Programming For The Rest Os Us</h2>

<p>Interested in FP? Be the first to be notified when new introductory
articles on the topic are published.<br /></p>

<iframe class="newsletter-subscription" src="https://embeds.beehiiv.com/55b1bb2e-e731-466f-8d1e-82b51d67a9ef?slim=true" data-test-id="beehiiv-embed" height="52" frameborder="0" scrolling="no" style="margin: 0; margin-top:5px; border-radius: 0px !important; background-color: transparent;"></iframe>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="tdd" /><category term="functional programming" /><category term="property-based testing" /><summary type="html"><![CDATA[Summaries From Matteo Vaccari: There’s no easy way to evolve the hardcoded values into general code. Alistair Cockburn said that this problem could be better solved by more mathematically-oriented thinking upfront about how many spaces should be generated where Emily Bache said that “recycling tests” is a valid way to iterate towards a difficult problem Other solutions came from Ron Jeffries, George Dinwiddie, Jon Jagger, again Ron Jeffries Francesco Cirillo Francesco Cirillo - The Diamond Kata Anti-IF Workshop Payed workshop. It promises that TDD and Anti-IF Programming “let design abstractions emerge […] in a way that prioritizes intentional design over algorithmic complexity, allowing for an adaptable and emergent solution.” It states: “No Thinking Ahead Required: Unlike conventional wisdom, this workshop will show you how to solve the Diamond Kata using TDD without the need for anticipatory thinking […] showing how abstractions emerge naturally through TDD.” Seb Rose Seb Rose - Recycling tests in TDD Seb uses the Print Diamond Kata in his trainings. He relies on the classical test progression (first the a case, then the b case, etc). He shows how some implementations are hardcoded (applying Fake It Until You Make It). He mentions the typical struggle with Example-Based TDD: “The code is now screaming for us to refactor it, but to keep all the tests passing most people try to solve the entire problem at once. That’s hard, because we’ll need to cope with multiple lines, varying indentation, and repeated characters with a varying number of spaces between them.” He suggests a second approach: “we start by decomposing the diamond problem into smaller constituent parts. This time I chose to write the following test:” He mentions the “the top half of the diamond”, without making it explicit it the code. He claims that “by recycling the second test multiple times, each time modifying the expected output to become closer to what we actual want, we’ve allowed ourselves to be guided gradually to a solution.” Here are the used tests: [TestFixture] public class DiamondTest { [Test] public void A_should_generate_a_single_character() { Assert.AreEqual("A", Diamond.Create('A')); } [Test] public void B_should_generate_the_smallest_diamond() { Assert.AreEqual(" A\nB B\n A", Diamond.Create('B')); } [Test] public void C_should_generate_the_next_diamond() { Assert.AreEqual(" A\n B B\nC C\n B B\n A", Diamond.Create('C')); } } and: using NUnit.Framework; [TestFixture] public class DiamondTest { [Test] public void A_should_give_single_character() { Assert.AreEqual("A\n", Diamond.Create('A')); } [Test] public void B_should_be_a_diamond() { Assert.AreEqual(" A\nB B\n A\n", Diamond.Create('B')); Assert.AreEqual(" A\n" + "B B\n" + " A\n", Diamond.Create('B')); } [Test] public void C_should_be_a_bigger_diamond() { string diamond = " A\n" + " B B\n" + "C C\n" + " B B\n" + " A\n"; Assert.AreEqual(diamond, Diamond.Create('C')); } [Test] public void D_should_be_an_even_bigger_diamond() { string diamond = " A\n" + " B B\n" + " C C\n" + "D D\n" + " C C\n" + " B B\n" + " A\n"; Assert.AreEqual(diamond, Diamond.Create('D')); } } Seb Rose - Diamond recycling (and painting yourself into a corner) Alistair Cockburn Alistair Cockburn - Thinking before programming “[…] a few professors had the idea that they might teach programmers to think a bit before hitting the keycaps. […]. They showed how to create programs (of a certain category) without error, by thinking about the properties of the problem and deriving the program as a small exercise in simple logic.” Accorging to Alistair XP and TDD “when practiced well, involve a different kind of thinking – not about the problem, but about the code. TDD has become a pablum to avoid thinking.” His approach is to combine the Dijkstra-Gries approach (thinking ahead) with TDD (“modern fine-grained incremental development”). In his premises, he seems to describe PBT: “What happens if we think about the problem and look for patterns and properties before starting, and then instead of typing the whole thing in at once, we “grow” the program using fine-grained incremental development and TDD?” Mentions the struggles about incremental development with TDD: Step 1: Go out and buy really good sneakers. Step 2: Do warmup exercises. Step 3: Jump really really really high, like, to the moon. “ He promises to reflect on the problem, not on the solution. He identifies some properties: The diamond is 2x+1 per 2x+1. For each row, there are 2x-1 spacers. There is a formula for leading and trailing spaces. Yet, he implements those ideas following the classical steps (case 0, then 1 etc). The formulas he conceived are the implementation. So, the test did not guide the design, to the point that he writes the implementation before the first test. Interestingly, the name of his tests have the typical “ForAll” form of a property test: def test_02_makes_and_fills_tray_of_any_size He claims that he did not type in all those tests at once, because “to do so is not only against the rules of TDD […]), but is actually dangerous”. I don’t agree with this: in fact, his implementation (the fomula he conceived) was already complete. The additional tests did not help evolving the formula. Even more interestingly, despite the initial good intuitions, his tests are a description of the solution, not the problem: :test_01_fills_first_and_last_slot_in_tray :test_02_makes_and_fills_tray_of_any_size :test_03_makes_bumper_for_row_in_diamond :test_04_glues_bumpers_to_tray_making_complete_row_in_diamond :test_05_makes_diamond_the_right_size :test_06_puts_a_row_in_both_upper_and_lower_half_of_diamond :test_07_digit_diamond_fills_correctly Notice the use of expressions like “the right size” and “fills correctly”. Jon Jagger Jon Jagger - sliming and refactoring and deliberate duplication Classic progression: a case, b case, c case, all hardcoded. He claims “As the tests get more specific, the code should get more generic. I have three specific tests, but the code is equally specific.” Beautful recursive implementation. Really brilliant. Yet, not induced by a test. Definitely, not an emergent design. George Dinwiddie George Dinwiddie - Another Approach to the Diamond Kata He also starts from the trivial degenerate diamond (with a hardcoded implementation). “The next step is obviously to implement the B case”. Why “obviously”? He refuses to hardcode B. His implementation, though, is not the minumum code strictly necessary to make the test pass, but already a generalization. Emily Bache Emily Bache - Iterative and Incremental TDD with the Diamond Kata She believes that “recycling tests” is a valid way to iterate towards a difficult problem Nothing new in her proposed repo, though: tests are incrementally going from A to D. Matteo Vaccari Matteo Vaccari - The Diamond Kata Revisited He acknowledges that “the problem statement is simple, but solving it with TDD is not straightforward” because “there’s no easy way to evolve the hardcoded values into general code”. Rather than trying to arrive at a “single algorithm” that will solve the problem in one shot, he suggests a compositional approach. He analyzes some traits of the problem (not the solution!), decomposing the problem into sub-problems and in fact capturing some properties, such as the symmetry of quadrants. Géza Mihala Géza Mihala - Diamond Kata Similarly to Matteo Vaccari, he plays with decomposing the problem (using functional decomposition). He also identifies 2 properties: horizontal and vertical symmetry. The 4 properties that define the problem are: a sequence of letters from ’A’ up to a given letter arranged diagonally in a square, padded with blanks mirrored to the left, not repeating the first column mirrored down, not repeating the bottom row The only missing step in his post is: he does not use TDD at all. References Resolved with Example-Based Testing Francesco Cirillo - The Diamond Kata Anti-IF Workshop Seb Rose - Recycling tests in TDD Seb Rose - Diamond recycling (and painting yourself into a corner) Alistair Cockburn - Thinking before programming Jon Jagger - sliming and refactoring and deliberate duplication George Dinwiddie - Another Approach to the Diamond Kata Emily Bache - Iterative and Incremental TDD with the Diamond Kata Emily Bache - DiamondKata repository Matteo Vaccari - The Diamond Kata Revisited Ron Jeffries - TDD on the Diamond Problem Ron Jeffries - More about Diamond Géza Mihala - Diamond Kata Resolved with Property-Based Testing Nat Pryce - Diamond Kata – TDD with only Property-Based Tests Mark Seemann - Diamond kata with FsCheck Uldis Sturms - property based testing in javascript - diamond kata Functional Programming For The Rest Os Us Interested in FP? Be the first to be notified when new introductory articles on the topic are published.]]></summary></entry><entry><title type="html">I suck at TDD (and how to fix it)</title><link href="http://arialdomartini.github.io/diamond" rel="alternate" type="text/html" title="I suck at TDD (and how to fix it)" /><published>2024-11-24T00:00:00+00:00</published><updated>2024-11-24T00:00:00+00:00</updated><id>http://arialdomartini.github.io/diamond</id><content type="html" xml:base="http://arialdomartini.github.io/diamond"><![CDATA[<p>How an innocuous Kata shows that either emergent design does not
exist, or that a better way of doing TDD is possible.</p>

<!--more-->
<h2 id="sirens">Sirens</h2>

<p>Test-Driven Development comes with 2 very seductive and ambitious
promises:</p>

<ul>
  <li>
    <p><strong>Development is really <em>driven</em> by tests</strong><br />
Not only do tests verify correctness; they also help determine what
code to write, in what order and how to structure it. In other words,
TDD helps shaping the software and determining its development
process.</p>
  </li>
  <li>
    <p><strong>There is an <em>Emergent Design</em></strong><br />
The system’s architecture and design incrementally take shape, rather
than being fully planned upfront.</p>
  </li>
</ul>

<p>It’s the alluring melody of a siren singing “Just write the tests and
abandon yourself to them: correctness and design will naturally
follow, incrementally”.</p>

<h2 id="reality">Reality</h2>
<p>Of course, this is too good to be exactly true. As Kent Beck writes in
<a href="https://tidyfirst.substack.com/p/tdd-isnt-design">TDD isn’t design</a>:</p>

<blockquote>
  <p>nobody with any sense says TDD replaces the need for design</p>
</blockquote>

<p>In fact, <em>Emergent Design</em>, in this context, has more the meaning
discussed in the C2 Wiki article <a href="https://wiki.c2.com/?CanAnArchitectureEmerge">Can An Architecture
Emerge</a>:</p>

<blockquote>
  <p>The term ‘emergent’ has a specific meaning with respect to chaos
theory. A structure, in the past, was always assumed to be imposed
by some direct structuring force. This is known as skeletal or
imposed structure. This would be an architecture that started
perfect and stayed that way.</p>

  <p>In this context, emergent means emerging from the system rather than
being imposed on the system. Take the example of a river’s
course. On the one hand the course of the river structures the flow
of water. Yet the flow of water is also responsible for defining the
course of the river.</p>
</blockquote>

<p>The question, then, is: can TDD lead an implementation without
requiring a design upfront?</p>

<p>Enter the Print Diamond Kata.</p>

<h2 id="print-diamond-kata">Print Diamond Kata</h2>

<p>The Print Diamond Kata (presented by Seb Rose in <a href="https://claysnow.co.uk/recycling-tests-in-tdd/">Recycling tests in
TDD</a>) is a very interesting exercise in that, if you
approach it with TDD by-the-book, it’s likely that you will struggle
to be <em>guided</em> by tests and to experience an emerging design. Instead,
you will be required to do some design upfront and to conceive a
solution from a light-bulb moment.<br />
Tests will help <em>challenging</em> your solution, not <em>conceiving</em> it. In a
sense, the Print Diamond Kata demonstrates that Emergent Design is not
always possible.</p>

<p>The problem is very simple: given a letter, you are supposed to return
a string with a diamond starting with <code class="language-plaintext highlighter-rouge">A</code> with the supplied letter at
the widest point.<br />
For example: <code class="language-plaintext highlighter-rouge">printDiamond('C')</code> returns:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  A
 B B
C   C
 B B
  A
</code></pre></div></div>

<p>The conventional way to approach it in TDD is to first get the <code class="language-plaintext highlighter-rouge">A</code>
case working — hardcoding the implementation — then to
follow with <code class="language-plaintext highlighter-rouge">B</code> and then with <code class="language-plaintext highlighter-rouge">C</code> etc.</p>

<p>As Alistair Cockburn commented in <a href="https://web.archive.org/web/20170621004437/http://alistair.cockburn.us/Thinking+before+programming">Thinking before
programming</a>:</p>

<blockquote>
  <p>What struck me in Seb’s recounting of people’s approach to the
problem is they first get the ‘A’ case working:</p>

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

  <p>Then they shuffle around a bit to get the ‘B’ case working:</p>

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

  <p>And then all the work that they did so far is of no use to them
whatsoever when they hit ‘C’, because that’s where all the
complexity is. In essence, they have to solve the entire problem,
and throw away masses of code, when they hit ‘C’.</p>

  <p>It reminds me of the story of incremental development and jumping to the moon:</p>

  <div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Step 1: Go out and buy really good sneakers.
Step 2: Do warmup exercises. 
Step 3: Jump really really really high, like, to the moon. 
</code></pre></div>  </div>

  <p>This is not the interesting form of incremental development. Can we do better?</p>
</blockquote>

<p>To me, this sounds like <a href="https://www.reddit.com/r/pics/comments/d3zhx/how_to_draw_an_owl">Clem Fandango’s “How To Draw A Owl”</a> meme:</p>

<p><img src="static/img/diamond/how-to-draw-an-owl.png" width="100%" /></p>

<p>Other developers way more experienced than me (see <a href="diamond-review">Review of other
devs’ approaches</a>) have observed more or less the
same.</p>

<p>This begs the question:</p>

<blockquote>
  <p><strong>Is it possible to apply TDD in a way that
tests really <em>drive</em> the implementation?</strong></p>
</blockquote>

<h2 id="we-suck-at-tdd">We suck at TDD</h2>

<p>I argue that the answer is a resounding “YES!”.<br />
And that the reason why many have experienced the opposite is because
of the way we classically apply TDD has some fundamental fallacies.</p>

<p>Once we revisit a bunch of the canonical assumptions we never dared to
question, it is indeed possible to have emergent design.<br />
That’s the goal of this article.</p>

<p>Along the way, I aim to debunk some myths:</p>

<ul>
  <li><em>100% code coverage</em> and <em>all green tests</em> mean <em>code correctness</em>
and <em>production readiness</em>.</li>
  <li>Understading <em>how much testing is enough</em> is a matter of skills and
experience, not a science.</li>
  <li>Tests in TDD are requirements expressed with code.</li>
</ul>

<h2 id="challenge">Challenge</h2>
<p>Before moving to the second part of this post, I invite you to try
yourself solving the Print Diamond Kata.</p>

<p>Notice: the goal is not just to <em>solve it</em>. The goal is <em>to challenge
that design can be driven by tests</em>. Therefore, I stress you to add
the following constraint:</p>

<blockquote>
  <p><strong>1.  Tests should neither depend on nor impose an implementation.</strong></p>
</blockquote>

<p>In other words, make sure not to take design decisions while writing
tests.</p>

<p>This resonates with the above-mentioned <a href="https://tidyfirst.substack.com/p/tdd-isnt-design">TDD isn’t
design</a>, that makes sense to quote more extensively:</p>

<blockquote>
  <p>Nobody with any sense says TDD replaces the need for design. The key
question is <em>when</em>.</p>

  <p>TDD offers:</p>

  <ul>
    <li>
      <p>Immediate feedback for interface design decisions. You still have
to make those decisions. [..]</p>
    </li>
    <li>
      <p>Separation between interface design decisions &amp; implementation
design decisions.</p>
    </li>
  </ul>
</blockquote>

<p>It also makes sense to have a second constraint:</p>

<blockquote>
  <p><strong>2. Each test gets to a deliverable result providing a business
     value increment</strong></p>
</blockquote>

<p>Make your game. While coding, pay attention if either</p>

<ul>
  <li>you can build on previous implentations</li>
  <li>or if you find youself in a <em>How to Draw an Owl</em> situation.</li>
</ul>

<p>When you are happy with your findings, let’s meet on the second part
of this post.</p>

<p>(Stay tuned…)</p>

<h1 id="references">References</h1>

<ul>
  <li><a href="https://tidyfirst.substack.com/p/tdd-isnt-design">Kent Beck - TDD isn’t design</a></li>
  <li><a href="https://wiki.c2.com/?EmergentDesign">C2 - Emergent Design</a></li>
  <li><a href="https://wiki.c2.com/?CanAnArchitectureEmerge">C2 - Can An Architecture Emerge</a></li>
  <li><a href="https://web.archive.org/web/20170621004437/http://alistair.cockburn.us/Thinking+before+programming">Alistair Cockburn - Thinking before programming</a></li>
  <li><a href="https://claysnow.co.uk/recycling-tests-in-tdd/">Seb Rose - Recycling tests in TDD</a></li>
  <li><a href="https://www.reddit.com/r/pics/comments/d3zhx/how_to_draw_an_owl">Clem Fandango - How To Draw A Owl</a></li>
</ul>

<h1 id="comments">Comments</h1>
<p><a href="https://github.com/arialdomartini/arialdomartini.github.io/discussions/33">GitHub Discussions</a></p>

<h2>Functional Programming For The Rest Os Us</h2>

<p>Interested in FP? Be the first to be notified when new introductory
articles on the topic are published.<br /></p>

<iframe class="newsletter-subscription" src="https://embeds.beehiiv.com/55b1bb2e-e731-466f-8d1e-82b51d67a9ef?slim=true" data-test-id="beehiiv-embed" height="52" frameborder="0" scrolling="no" style="margin: 0; margin-top:5px; border-radius: 0px !important; background-color: transparent;"></iframe>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="tdd" /><category term="functional programming" /><category term="property-based testing" /><summary type="html"><![CDATA[How an innocuous Kata shows that either emergent design does not exist, or that a better way of doing TDD is possible.]]></summary></entry><entry><title type="html">xUnit tips its hat to Property-Based Testing</title><link href="http://arialdomartini.github.io/xunit-property" rel="alternate" type="text/html" title="xUnit tips its hat to Property-Based Testing" /><published>2024-11-05T00:00:00+00:00</published><updated>2024-11-05T00:00:00+00:00</updated><id>http://arialdomartini.github.io/xunit-property</id><content type="html" xml:base="http://arialdomartini.github.io/xunit-property"><![CDATA[<p>Ever wondered why parametric tests in xUnit are called “<em>theories</em>”?
And why are tests called “<em>facts</em>” instead of, well, just “<em>tests</em>”?</p>

<p>Investigating on this topic helped me realize that I have always used
xUnit theories incorrectly. And that xUnit loves the idea of
Property-Based Testing.</p>

<!--more-->

<p>I’ve been tought to use xUnit theories as a mere trick to repeat a
test with different inputs, without incurring in duplication:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">2</span><span class="p">,</span> <span class="k">true</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">4</span><span class="p">,</span> <span class="k">true</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">3</span><span class="p">,</span> <span class="k">false</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">7</span><span class="p">,</span> <span class="k">false</span><span class="p">)]</span>
<span class="k">void</span> <span class="nf">check_if_odd_or_even</span><span class="p">(</span><span class="kt">int</span> <span class="n">number</span><span class="p">,</span> <span class="kt">bool</span> <span class="n">expectedResult</span><span class="p">)</span>
<span class="p">{</span>
    <span class="kt">var</span> <span class="n">actualResult</span> <span class="p">=</span> <span class="nf">IsEven</span><span class="p">(</span><span class="n">number</span><span class="p">);</span>
    
    <span class="n">Assert</span><span class="p">.</span><span class="nf">Equal</span><span class="p">(</span><span class="n">expectedResult</span><span class="p">,</span> <span class="n">actualResult</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p>Like in this dummy example, I’ve always been used  have an
<code class="language-plaintext highlighter-rouge">expectedResult</code> parameter.</p>

<h2 id="theorys-purpose">Theory’s purpose</h2>

<p>I then realized that this is not the style used in the <a href="https://xunit.net/docs/getting-started/v3/cmdline">xUnit
manual</a>. The chapter <a href="https://xunit.net/docs/getting-started/v3/cmdline#write-your-first-theory">Write your first theory</a>
never mentions any argument like my <code class="language-plaintext highlighter-rouge">expectedResult</code>. Instead, it uses
this style:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">3</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">5</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">6</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">MyFirstTheory</span><span class="p">(</span><span class="kt">int</span> <span class="k">value</span><span class="p">)</span>
<span class="p">{</span>
    <span class="n">Assert</span><span class="p">.</span><span class="nf">True</span><span class="p">(</span><span class="nf">IsOdd</span><span class="p">(</span><span class="k">value</span><span class="p">));</span>
<span class="p">}</span>

<span class="kt">bool</span> <span class="nf">IsOdd</span><span class="p">(</span><span class="kt">int</span> <span class="k">value</span><span class="p">)</span>
<span class="p">{</span>
    <span class="k">return</span> <span class="k">value</span> <span class="p">%</span> <span class="m">2</span> <span class="p">==</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>

<p>It claims that a <em>property</em> (“to be odd”) holds for a set of inputs.
Indeed, it was introduced by this sentence:</p>

<blockquote>
  <p>You may have wondered why your first unit tests use an attribute
named [Fact] rather than one with a more traditional name like Test.
xUnit.net includes support for two different major types of unit
tests: facts and theories. When describing the difference between
facts and theories, we like to say:</p>

  <ul>
    <li>
      <p>Facts are tests which are always true. They test invariant
conditions.</p>
    </li>
    <li>
      <p>Theories are tests which are only true for a particular set of
data.</p>
    </li>
  </ul>
</blockquote>

<p>Under this light, <em>Theories</em> remind me of <em>Properties</em> in
<a href="https://arialdomartini.github.io/property-testing">Property-Based Testing</a>.<br />
Ideally, xUnit designers could have decided to let theories run
against a predicate, and let them assume success if the predicate is
true, failure otherwise:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="n">Theory</span><span class="p">]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">3</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">5</span><span class="p">)]</span>
<span class="p">[</span><span class="nf">InlineData</span><span class="p">(</span><span class="m">6</span><span class="p">)]</span>
<span class="k">public</span> <span class="k">void</span> <span class="nf">MyFirstTheory</span><span class="p">(</span><span class="kt">int</span> <span class="k">value</span><span class="p">)</span> <span class="p">=&gt;</span>
    <span class="nf">IsOdd</span><span class="p">(</span><span class="k">value</span><span class="p">));</span>
</code></pre></div></div>

<p>Add a way to generate inputs and you would have Property-Based
Testing.</p>

<h2 id="further-details">Further details</h2>
<p>Am I going too far?<br />
I thought so. Then I stubled upon a comment to the <a href="https://github.com/xunit/xunit/discussions/2822">xUnit Issue
#2822 - Why the word “[Theory]” as opposed to something like
“[MultiFact]”?</a>:</p>

<p><a href="https://github.com/bartelink">Ruben Bartelink</a> observed in his <a href="https://github.com/xunit/xunit/discussions/2822#discussioncomment-7593309">comment</a>:</p>

<blockquote>
  <p>It’s just naming; The names are accentuating the role it plays vs a
lower level description of what it technically does/is. […] you
can argue it puts authors in the right frame of mind. Or you can
argue that it’s cryptic. But xUnit is definitely designed with lots
of though put into nuanced design aspects with a view to nudging one
towards writing good tests, and shaping good systems.</p>
</blockquote>

<p>So, this is indeed very intentional and about promoting a specific
testing style. Going ahead (bold is mine):</p>

<blockquote>
  <p>In xUnit<br />
A Fact is an individual relevant assertion. If you have 3 of them,
they may or may not mean anything in aggregate.<br />
<strong>A Theory is a set of facts that together prove an overall
concept</strong><br />
<strong>In Property Based Testing, a Property is called that because
that’s its role - It’s not a
<code class="language-plaintext highlighter-rouge">TestWithMultipleInvocationsBasedOnArbitraryData</code>. We are specifting
a property of the system under test</strong>.</p>
</blockquote>

<p>So, I’m not alone observing a similarity with PBT.</p>

<p><a href="https://github.com/bradwilson">Brad Wilson</a>, xUnit’s caretaker,
<a href="https://github.com/xunit/xunit/discussions/2822#discussioncomment-7602733">commented</a>
quoting the page <a href="https://xunit.net/docs/why-did-we-build-xunit-1.0">Why Did we Build xUnit 1.0?</a>:</p>

<blockquote>
  <p>The definition of how to run a test method can be extended. There
are two example of this: the first, in xunitext.dll, is the [Theory]
attribute which allows data-driven tests; the second, in the
samples, is the [RepeatTest] attribute which runs a test method
multiple times in a row. For more information on data theories, see
 https://homes.cs.washington.edu/~mernst/pubs/testing-theories-tr002-abstract.html.</p>
</blockquote>

<p>Down the rabbit hole, here is an excerpt of the paper’s abstract (bold
is mine):</p>

<blockquote>
  <p>Traditional test suites verify a few well-picked scenarios or
example inputs. […] We propose <strong>theory-based testing as
an adjunct to example-based testing</strong>.<br />
<strong>A theory generalizes a (possibly infinite) set of example-based
tests. A theory is an assertion that should be true for any data,
and it can be exercised by human-chosen data or by automatic data
generation.</strong></p>
</blockquote>

<p>Here are some code examples from the paper. In the first one:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kt">void</span> <span class="nf">additionIsInverseOfSubtraction</span><span class="o">(</span><span class="kt">int</span> <span class="n">x</span><span class="o">,</span> <span class="kt">int</span> <span class="n">y</span><span class="o">)</span> <span class="o">{</span>
    <span class="n">assertEquals</span><span class="o">(</span><span class="n">x</span><span class="o">,</span> <span class="o">(</span><span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="o">)</span> <span class="o">-</span> <span class="n">y</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>

<p>the assertion should hold over the entire valid input space. In the
following:</p>

<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Theory</span>
<span class="kt">void</span> <span class="nf">equalObjectsEqualHashes</span><span class="o">(</span><span class="nc">Object</span> <span class="n">a</span><span class="o">,</span> <span class="nc">Object</span> <span class="n">b</span><span class="o">)</span> <span class="o">{</span>
  <span class="n">assumeTrue</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">b</span><span class="o">));</span>
  <span class="n">assertTrue</span><span class="o">(</span><span class="n">a</span><span class="o">.</span><span class="na">hashCode</span><span class="o">()</span> <span class="o">==</span> <span class="n">b</span><span class="o">.</span><span class="na">hashCode</span><span class="o">());</span>
<span class="o">}</span>
</code></pre></div></div>

<p>the assumption expressed by <code class="language-plaintext highlighter-rouge">assumeTrue</code> further restricts which
inputs are valid for evaluating the assertion.</p>

<p>In one of the last chapters, the paper introduces the idea of a
<em>Theory Explorer</em>, an input generator based on Agitator, used to find
inputs that will cause the theory to fail.</p>

<p>This Theory-Based Testing is really akin to Property-Based Testing.
The paper even mentions the classical test on reversing a string and
Haskell’s <a href="https://www.cse.chalmers.se/~rjmh/QuickCheck/">QuickCheck</a>, which predates the paper by 9
years. No mention to PBT is present, though.</p>

<h2 id="my-conclusion">My conclusion</h2>
<p>xUnit is not a Property-Based Testing library, and it’s unlikely to
evolve into one anytime soon.<br />
In <a href="https://arialdomartini.github.io/property-testing">Property-Based Testing for The Rest of Us</a> I argue that
the value of PBT lies not primarily in the random generation of
inputs; instead, it comes from how it encourages developers to gain a
deeper and reasoned undertanding of requirements, compared to
example-based testing.</p>

<p>My take away is: it is worth to use theories the way they have been
originally conceived and designed. I bet that the mere attempt not to
use any <code class="language-plaintext highlighter-rouge">expectedResult</code> argument is very likely to bring to more
profound and effective tests.</p>

<h2 id="references">References</h2>

<ul>
  <li><a href="https://xunit.net/docs/why-did-we-build-xunit-1.0">Why Did we Build xUnit 1.0?</a></li>
  <li><a href="https://github.com/xunit/xunit/discussions/2822">xUnit Issue #2822 - Why the word “[Theory]” as opposed to
something like “[MultiFact]”?</a></li>
  <li><a href="https://xunit.net/docs/getting-started/v3/cmdline#write-your-first-theory">xUnit manual - Write your first theory</a></li>
  <li><a href="https://homes.cs.washington.edu/~mernst/pubs/testing-theories-tr002-abstract.html">Theories in practice: Easy-to-write specifications that catch
bugs</a></li>
  <li><a href="https://www.cse.chalmers.se/~rjmh/QuickCheck/">QuickCheck</a></li>
  <li><a href="https://arialdomartini.github.io/property-testing">Property-Based Testing for The Rest of Us</a></li>
</ul>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="functional programming" /><category term="tdd" /><category term="pbt" /><summary type="html"><![CDATA[Ever wondered why parametric tests in xUnit are called “theories”? And why are tests called “facts” instead of, well, just “tests”? Investigating on this topic helped me realize that I have always used xUnit theories incorrectly. And that xUnit loves the idea of Property-Based Testing.]]></summary></entry><entry><title type="html">Emacs: let’s zoom</title><link href="http://arialdomartini.github.io/emacs-zoom" rel="alternate" type="text/html" title="Emacs: let’s zoom" /><published>2024-11-05T00:00:00+00:00</published><updated>2024-11-05T00:00:00+00:00</updated><id>http://arialdomartini.github.io/emacs-zoom</id><content type="html" xml:base="http://arialdomartini.github.io/emacs-zoom"><![CDATA[<p>Let’s develop <code class="language-plaintext highlighter-rouge">squint</code> a little package for controlling the font
height, so you won’t need to squint your eyes when you are on smaller
screens.<br />
It will look like this:</p>

<p><img width="100%" src="/static/img/emacs/squint/squint.gif" /></p>

<p>It will give us the chance to touch on:</p>

<ul>
  <li>Face attributes.</li>
  <li>Asking the user to choose interactively from a list of options.</li>
  <li>The powerful <code class="language-plaintext highlighter-rouge">consult--read</code>.</li>
  <li>Lisp’s Dynamic and Lexical Binding.</li>
  <li>Few other little topics here and there.</li>
</ul>

<!--more-->

<h2 id="faces">Faces</h2>

<p>In Emacs, the “face” is the visual styling attribute that can be
applied to text: faces define how text appears on the screen,
including the font, the colors, and the weight. And the height, the
attribute we want to control in this little tutorial.</p>

<p>There is a notion of “default face” in Emacs: it’s basically the
parent from which all the other faces inherit their attributes, unless
they specify a specialization. Changing an attribute of the default
face will propagate the change everywhere in Emacs.</p>

<p>Try yourself. Open your scratch buffer (<code class="language-plaintext highlighter-rouge">M-x scratch-buffer RET</code>) and
write:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">face-attribute</span> <span class="ss">'default</span> <span class="ss">:height</span><span class="p">)</span>
</code></pre></div></div>

<p>Evaluate it: move right after the last <code class="language-plaintext highlighter-rouge">)</code> and hit <code class="language-plaintext highlighter-rouge">C-j</code> (or <code class="language-plaintext highlighter-rouge">M-x
eval-print-last-sexp RET</code>). This reveals the current height of the
default face. In my case, it prints <code class="language-plaintext highlighter-rouge">180</code>.</p>

<p>Good. Now, try to change it:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="mi">100</span><span class="p">)</span>
</code></pre></div></div>

<p>Evaluate it: again, move right after the last <code class="language-plaintext highlighter-rouge">)</code> and hit <code class="language-plaintext highlighter-rouge">C-x
C-e</code>. As expected, any text in Emacs will inherit the new defined
height.</p>

<p>Cool, you learnt how to programmatically control the global text
height.<br />
There are other attributes you can control, such as the foreground and
background colors, the weight and the font. You can learn more about
this topic from the chapter <a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Faces.html">Faces</a> in the Emacs Manual.<br />
But let’s focus on height.</p>

<h2 id="controlling-the-current-buffer-faces">Controlling the current buffer faces</h2>

<p><code class="language-plaintext highlighter-rouge">set-face-attribute</code> operates globally. If you want to control the
faces of the current buffer only, you need to play with
<em>remappings</em>. I will skate over this topic, but just quickly:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">cookie</span>
      <span class="p">(</span><span class="nv">face-remap-add-relative</span> <span class="ss">'default</span> <span class="ss">:height</span> <span class="mi">280</span><span class="p">))</span>
</code></pre></div></div>

<p>changes the height of the default face <em>in the current buffer
only</em>. Indeed, it creates a <em>remap</em> of the face, that is a way to
temporarily redirecting how a face is displayed.</p>

<p>It returns a <em>cookie</em>, that we save in the <code class="language-plaintext highlighter-rouge">cookie</code> variable. When you
want to remove the remap, you have to provide that cookie to
<code class="language-plaintext highlighter-rouge">face-remap-remove-relative</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">face-remap-remove-relative</span> <span class="nv">cookie</span><span class="p">)</span>
</code></pre></div></div>

<p>We won’t need to worry about this: our <code class="language-plaintext highlighter-rouge">squint</code> package will operate
globally.</p>

<h2 id="controlling-the-height-interactively">Controlling the height interactively</h2>

<p>There are 2 ways for interactively modifying the size of characters on
the screen:</p>

<table>
  <thead>
    <tr>
      <th>Command</th>
      <th>Keybindings</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">(text-scale-adjust)</code></td>
      <td><code class="language-plaintext highlighter-rouge">C-x C-0</code> <br /> <code class="language-plaintext highlighter-rouge">C-x C-=</code> <br /> <code class="language-plaintext highlighter-rouge">C-x C--</code> <br /> <code class="language-plaintext highlighter-rouge">C-x C-+</code></td>
      <td>Adjust the font size in the current buffer</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">(global-text-scale-adjust)</code></td>
      <td><code class="language-plaintext highlighter-rouge">C-x C-M-0</code> <br /> <code class="language-plaintext highlighter-rouge">C-x C-M--</code> <br /> <code class="language-plaintext highlighter-rouge">C-x C-M-=</code> <br /> <code class="language-plaintext highlighter-rouge">C-x C-M-+.</code></td>
      <td>Adjust the font size in globally</td>
    </tr>
  </tbody>
</table>

<p>They are straightforward to use: activate them, then follow the
instructions on the screen, hitting:</p>

<table>
  <thead>
    <tr>
      <th>Key</th>
      <th>Purpose</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">+</code></td>
      <td>Increase the height</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">-</code>,</td>
      <td>Decrease the height</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">0</code></td>
      <td>Reset the height</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">ESC</code></td>
      <td>Quit the interactive session</td>
    </tr>
  </tbody>
</table>

<p>That easy.</p>

<h2 id="grab-your-keeb">Grab your keeb</h2>
<p>Enough with theory. Our goal is to create a new command, <code class="language-plaintext highlighter-rouge">squint</code>,
offering a list of height presets to choose from interactively, with
narrowing and realtime preview.</p>

<p>We will proceed incrementally, each time improving the result.</p>

<h3 id="step-1-set-height-from-keyvalue-pairs">Step 1: set height from key/value pairs</h3>

<p>The basic idea is to have a collection of heights in an alist (see
<a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Association-Lists.html">Association Lists</a>), that is a list of key-value pairs, such
as:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="s">"office"</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="s">"laptop"</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="s">"programming"</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)</span>
        <span class="p">(</span><span class="s">"presentation"</span> <span class="o">.</span> <span class="mi">300</span><span class="p">)))</span>
</code></pre></div></div>

<p>and to set the corresponding height through its label, with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">squint</span> <span class="s">"presentation"</span><span class="p">)</span>
<span class="p">(</span><span class="nv">squint</span> <span class="s">"laptop"</span><span class="p">)</span>
</code></pre></div></div>

<p>It does not sound as a very challenging problem, does it? We need to
define a function <code class="language-plaintext highlighter-rouge">squint</code> that:</p>

<ul>
  <li>Given a label, retrieves the corresponding height from
<code class="language-plaintext highlighter-rouge">squint-heights</code>.</li>
  <li>Once obtained the height, uses the <code class="language-plaintext highlighter-rouge">set-face-attribute</code> we saw
before to adjust the font height.</li>
</ul>

<p>Retrieving a value given a key from an alist is simply done with
<code class="language-plaintext highlighter-rouge">alist-get</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">alist-get</span> <span class="s">"programming"</span> <span class="nv">squint-heights</span> <span class="no">nil</span> <span class="no">nil</span> <span class="nf">#'</span><span class="nb">equal</span><span class="p">)</span>
</code></pre></div></div>

<p>Here’s the signature:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>(alist-get 
    KEY     ;; the key to search for
    ALIST   ;; the alist to search in
    DEFAULT ;; the value to return in case KEY is not found
    REMOVE  ;; whether the pair should be removed in case of success
    TESTFN) ;; the equality function to use for comparing keys
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">TESTFN</code> defaults to <code class="language-plaintext highlighter-rouge">eq</code>, which is a bit unfortunate: <code class="language-plaintext highlighter-rouge">eq</code> does not
return true if the two args are equal, but only if they are the very
same Lisp object. In other words,</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">eq</span> <span class="s">"ciao"</span> <span class="s">"ciao"</span><span class="p">)</span>
</code></pre></div></div>

<p>is false: although the 2 strings are equal, they are not the same
object.<br />
This:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">ciao</span> <span class="s">"ciao"</span><span class="p">)</span>
<span class="p">(</span><span class="nb">eq</span> <span class="nv">ciao</span> <span class="nv">ciao</span><span class="p">)</span>
</code></pre></div></div>

<p>returns true.<br />
Instead of <code class="language-plaintext highlighter-rouge">eq</code> we’d better use <code class="language-plaintext highlighter-rouge">equal</code> which, more conveniently,
returns true if two objects have similar structure and contents.<br />
Since <code class="language-plaintext highlighter-rouge">TESTFN</code> is a positional parameter, we are also forced to
provide 2 <code class="language-plaintext highlighter-rouge">nil</code> values for the other parameters <code class="language-plaintext highlighter-rouge">DEFAULT</code> and
<code class="language-plaintext highlighter-rouge">REMOVE</code>.</p>

<p>That’s all you need to know to finally define:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="s">"office"</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="s">"laptop"</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="s">"programming"</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)</span>
        <span class="p">(</span><span class="s">"presentation"</span> <span class="o">.</span> <span class="mi">300</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="s">"Adjust font height based on predefined settings.
LABEL is a string that corresponds to a key in `squint-heights'."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">height</span> <span class="p">(</span><span class="nv">alist-get</span> <span class="nv">label</span> <span class="nv">squint-heights</span> <span class="no">nil</span> <span class="no">nil</span> <span class="nf">#'</span><span class="nb">equal</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="nv">height</span><span class="p">)))</span>
</code></pre></div></div>

<p>Evaluate the code above (<code class="language-plaintext highlighter-rouge">C-x C-e</code> after each expression), then run:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">squint</span> <span class="s">"presentation"</span><span class="p">)</span>
</code></pre></div></div>

<p>Such a large font! Sweet!</p>

<h3 id="step-2-symbols-instead-of-strings">Step 2: symbols instead of strings</h3>
<p>The quirk about using <code class="language-plaintext highlighter-rouge">equal</code> can be avoided using <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbols.html">symbols</a>
(such as <code class="language-plaintext highlighter-rouge">'office</code> and <code class="language-plaintext highlighter-rouge">'laptop</code>) instead of strings such as
<code class="language-plaintext highlighter-rouge">"office"</code> and <code class="language-plaintext highlighter-rouge">"laptop"</code>.</p>

<p>With strings one must be careful when to use <code class="language-plaintext highlighter-rouge">eq</code> and when to use <code class="language-plaintext highlighter-rouge">equal</code>:</p>

<table>
  <thead>
    <tr>
      <th>Expression</th>
      <th>Value</th>
      <th>Comment</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">(eq "office" "office")</code></td>
      <td><code class="language-plaintext highlighter-rouge">nil</code></td>
      <td>Although equal, the 2 are different objects.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">(equal "office" "office")</code></td>
      <td><code class="language-plaintext highlighter-rouge">t</code></td>
      <td><code class="language-plaintext highlighter-rouge">equal</code> compares the value.</td>
    </tr>
  </tbody>
</table>

<p>With symbols, equality is much easier:</p>

<table>
  <thead>
    <tr>
      <th>Expression</th>
      <th>Value</th>
      <th>Comment</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">(eq 'office 'office)</code></td>
      <td><code class="language-plaintext highlighter-rouge">t</code></td>
      <td>All symbols called <code class="language-plaintext highlighter-rouge">'office</code> are the very same instance.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">(equal 'office 'office)</code></td>
      <td><code class="language-plaintext highlighter-rouge">t</code></td>
      <td><code class="language-plaintext highlighter-rouge">'office</code>’s value is <code class="language-plaintext highlighter-rouge">'office</code>, so <code class="language-plaintext highlighter-rouge">equal</code> is true too.</td>
    </tr>
  </tbody>
</table>

<p>Let’s try redefining <code class="language-plaintext highlighter-rouge">squint-heights</code> using symbols instead of strings
for its keys:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">300</span><span class="p">)))</span>
</code></pre></div></div>

<p>The usage of <code class="language-plaintext highlighter-rouge">alist-get</code> is a bit shorter:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">alist-get</span> <span class="ss">'programming</span> <span class="nv">squint-heights</span><span class="p">)</span>
</code></pre></div></div>

<p>Notice the use of <code class="language-plaintext highlighter-rouge">'programming</code> instead of <code class="language-plaintext highlighter-rouge">"programming"</code>.<br />
This leads to the following simplified implementation:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="s">"Adjust font height based on predefined settings.
LABEL is a symbol that corresponds to a key in `squint-heights'."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">height</span> <span class="p">(</span><span class="nv">alist-get</span> <span class="nv">label</span> <span class="nv">squint-heights</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="nv">height</span><span class="p">)))</span>
</code></pre></div></div>

<p>Invoke it with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">squint</span> <span class="ss">'presentation</span><span class="p">)</span>
</code></pre></div></div>

<p>Still works.</p>

<h3 id="step-3---helper-functions">Step 3 - Helper functions</h3>
<p>Indulge me while I extract a few private functions. They will come in handy
when we will change the behavior in the next steps.<br />
In:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="s">"Adjust font height based on predefined settings.
LABEL is a symbol that corresponds to a key in `squint-heights'."</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">height</span> <span class="p">(</span><span class="nv">alist-get</span> <span class="nv">label</span> <span class="nv">squint-heights</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="nv">height</span><span class="p">)))</span>
</code></pre></div></div>

<p>we would like to have a function <code class="language-plaintext highlighter-rouge">squint--height-from-label</code> returning
the height given the label. That’s easy:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">alist-get</span> <span class="nv">label</span> <span class="nv">squint-heights</span><span class="p">))</span>
</code></pre></div></div>

<p>Then, we could abstract the details of changing the face attribute
with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">height</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="nv">height</span><span class="p">))</span>
  
<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">))</span>
</code></pre></div></div>

<p>Putting all together:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">alist-get</span> <span class="nv">label</span> <span class="nv">squint-heights</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">height</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="nv">height</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="nv">label</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="s">"Adjust font height based on predefined settings.
LABEL is a symbol that corresponds to a key in `squint-heights'."</span>
  <span class="p">(</span><span class="nv">squint--set-height-from-label</span> <span class="nv">label</span><span class="p">))</span>
</code></pre></div></div>

<p>That’s all. Verify that:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">squint</span> <span class="ss">'programming</span><span class="p">)</span>
</code></pre></div></div>

<p>still works.</p>

<h3 id="step-4---making-squint-interactive">Step 4 - Making squint interactive</h3>
<p>Although you have defined <code class="language-plaintext highlighter-rouge">squint</code>, there is no sign of it in the list
of commands displayed when you hit <code class="language-plaintext highlighter-rouge">M-x</code>. Yet, the function is defined
globally: invoking <code class="language-plaintext highlighter-rouge">M-x describe-function RET squint RET</code> you can even
read its documentation.</p>

<p>The fact is: <code class="language-plaintext highlighter-rouge">M-x</code> only lists <em>commands</em>, i.e., those functions that
are explicitly declared as interactive.</p>

<p>Well, let’s make <code class="language-plaintext highlighter-rouge">squint</code> interactive then:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="s">"Adjust font height based on predefined settings.
LABEL is a symbol that corresponds to a key in `squint-heights'."</span>
  <span class="p">(</span><span class="nv">squint--set-height-from-label</span> <span class="nv">label</span><span class="p">))</span>
</code></pre></div></div>

<p>Is this enough? Try yourself: hit <code class="language-plaintext highlighter-rouge">M-x squint RET</code> and you will get
back the error:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>funcall-interactively: Wrong number of arguments: 
  #[(label) (nil (squint--set-height-from-label label)) nil nil nil nil], 0
</code></pre></div></div>

<p>The problem is: the poor <code class="language-plaintext highlighter-rouge">(interactive)</code> function might even
understand that it needs to ask the user for a <code class="language-plaintext highlighter-rouge">label</code> argument, but
it cannot possibly figure out if this is a file, a string, a number or
a symbol from a list, such as in our case. You must give it a hint.<br />
Enter <code class="language-plaintext highlighter-rouge">completing-read</code>.</p>

<h3 id="completing-read">completing-read</h3>
<p>Try:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">completing-read</span>
 <span class="s">"Choose your poison: "</span>
 <span class="o">'</span><span class="p">(</span><span class="s">"arsenic"</span> <span class="s">"digitalis"</span> <span class="s">"strychnine"</span> <span class="s">"belladonna"</span><span class="p">))</span>
</code></pre></div></div>

<p>Evaluate it, make your choice and notice how it returns the selected
string.<br />
Does it work with symbols too?</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">symbols</span>
      <span class="o">'</span><span class="p">(</span><span class="nv">office</span> <span class="nv">laptop</span> <span class="nv">programming</span> <span class="nv">presentation</span><span class="p">))</span>

<span class="p">(</span><span class="nv">completing-read</span>
 <span class="s">"Choose your poison: "</span>
 <span class="nv">symbols</span><span class="p">)</span>
</code></pre></div></div>

<p>Yes, it does! But notice: you gave it a symbols, it returns a
string. Weird, but it is like it is.<br />
What if you feed it with an alist?</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">completing-read</span>
 <span class="s">"Choose your poison: "</span>
 <span class="nv">squint-heights</span><span class="p">)</span>
</code></pre></div></div>

<p>It still works, and it still returns the key as a string. Yes, it
would have been easier if it returned the value rather then the key,
but that’s life.</p>

<p>You can combine <code class="language-plaintext highlighter-rouge">interactive</code> with <code class="language-plaintext highlighter-rouge">completing-read</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">alist-get</span> <span class="nv">label</span> <span class="nv">squint-heights</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">height</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="nv">height</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="nv">label</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">interactive</span> 
   <span class="p">(</span><span class="nv">completing-read</span> <span class="s">"Desired height: "</span> <span class="nv">squint-heights</span><span class="p">))</span>
  <span class="s">"Adjust font height based on predefined settings.
LABEL is a symbol that corresponds to a key in `squint-heights'."</span>
  <span class="p">(</span><span class="nv">squint--set-height-from-label</span> <span class="nv">label</span><span class="p">))</span>
</code></pre></div></div>

<p>Try <code class="language-plaintext highlighter-rouge">M-x squint</code> now. Good: now it shows an interactive menu to choose
from.<br />
Make your choice, hit <code class="language-plaintext highlighter-rouge">RET</code> and be disappointed seing the debug window
screaming:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>squint--set-height: Default face height not absolute and positive
</code></pre></div></div>

<p>What’s wrong?<br />
There are 2 issues:</p>

<ul>
  <li>The first is how we use <code class="language-plaintext highlighter-rouge">interactive</code>. If only we spent the time to
consult its documentation (<code class="language-plaintext highlighter-rouge">M-x describe-function RET interactive
RET</code>) we would have seen this line:</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>If the argument is not a string, it is evaluated to get a list of
 arguments to pass to the command.
</code></pre></div></div>

<p>We have:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="p">(</span><span class="nv">interactive</span> 
   <span class="p">(</span><span class="nv">completing-read</span> <span class="s">"Desired height: "</span> <span class="nv">squint-heights</span><span class="p">))</span>
</code></pre></div></div>

<p>and we know that <code class="language-plaintext highlighter-rouge">completing-read</code> returns a string (indeed: the
selected key, as a string), not a list. Indeed, <code class="language-plaintext highlighter-rouge">interactive</code> must
work for an arbitrary number of parameters, so it makes sense it
expects a list.<br />
We can easily fix this surrounding <code class="language-plaintext highlighter-rouge">completing-read</code> with a list
constructor:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="p">(</span><span class="nb">list</span>
                <span class="p">(</span><span class="nv">completing-read</span> <span class="s">"Desired height: "</span> <span class="nv">squint-heights</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">squint--set-height-from-label</span> <span class="nv">label</span><span class="p">))</span>
</code></pre></div></div>

<ul>
  <li>The second problem could also be easily forseen: <code class="language-plaintext highlighter-rouge">completing-read</code>
returns a string, but our <code class="language-plaintext highlighter-rouge">squint--height-from-label</code> expects a
symbol, because the <code class="language-plaintext highlighter-rouge">squint-heights</code> alist uses symbols as keys.<br />
Here is where having refactored those helper functions away pays
off. We can use the function <code class="language-plaintext highlighter-rouge">intern</code>, that returns a symbol given a
string:</li>
</ul>

<p>Just change:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">alist-get</span> <span class="nv">label</span> <span class="nv">squint-heights</span><span class="p">))</span>
</code></pre></div></div>

<p>to:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">alist-get</span> <span class="p">(</span><span class="nb">intern</span> <span class="nv">label</span><span class="p">)</span> <span class="nv">squint-heights</span><span class="p">))</span>
</code></pre></div></div>

<p>Putting all together:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">alist-get</span> <span class="p">(</span><span class="nb">intern</span> <span class="nv">label</span><span class="p">)</span> <span class="nv">squint-heights</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">height</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="nv">height</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="nv">label</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="p">(</span><span class="nb">list</span>
                <span class="p">(</span><span class="nv">completing-read</span> <span class="s">"Desired height: "</span> <span class="nv">squint-heights</span><span class="p">)))</span>
  <span class="p">(</span><span class="nv">squint--set-height-from-label</span> <span class="nv">label</span><span class="p">))</span>
</code></pre></div></div>

<p>Try <code class="language-plaintext highlighter-rouge">M-x squint RET</code> (or, if you developed a taste for writing lisp,
evaluate <code class="language-plaintext highlighter-rouge">(call-interactively #'squint)</code>): it will equally work.</p>

<h3 id="step-5---preview-preview">Step 5 - Preview! Preview!</h3>
<p><code class="language-plaintext highlighter-rouge">completing-read</code> does already a lot.</p>

<ul>
  <li>It lets you select the preset with arrow keys.</li>
  <li>It sorts the options accordingly to their most recent usage.</li>
  <li>It lets you filter by typing (try typing  <code class="language-plaintext highlighter-rouge">"prog""</code> to see the list
interactively narrow down to <code class="language-plaintext highlighter-rouge">programming</code>).</li>
</ul>

<p>The next cool feature you might desire to have is a real-time
preview. That is, the very moment you move on a candidate, even before
confirming the selection, you would like to see its effect in
place. Then:</p>

<ul>
  <li>Confirming the selection would keep the new height.</li>
  <li>Canceling the selection, it would be nice to reset to the previous
height.</li>
</ul>

<p>This is much more challenging to implement. But maybe we can start by
reusing what the magnificent <a href="https://github.com/minad/consult">consult</a> package offers.</p>

<p>If you don’t have consult installed yet, show deep remorse, publicly express
shame and amend by adding something like this to your init file:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">consult</span>
  <span class="ss">:ensure</span> <span class="no">t</span>
  <span class="ss">:demand</span> <span class="no">t</span>
  <span class="ss">:bind</span> <span class="p">((</span><span class="s">"M-g M-g"</span> <span class="o">.</span> <span class="nv">consult-goto-line</span><span class="p">)</span>
         <span class="p">(</span><span class="s">"C-x b"</span> <span class="o">.</span> <span class="nv">consult-buffer</span><span class="p">)</span>
         <span class="p">(</span><span class="s">"C-s"</span>   <span class="o">.</span> <span class="nv">consult-line</span><span class="p">)</span>
         <span class="p">(</span><span class="s">"C-S-s"</span> <span class="o">.</span> <span class="nv">isearch-forward</span><span class="p">)</span>
         <span class="p">(</span><span class="s">"C-x r b"</span> <span class="o">.</span> <span class="nv">consult-bookmark</span><span class="p">)</span>
         <span class="p">(</span><span class="s">"M-y"</span> <span class="o">.</span> <span class="nv">consult-yank-pop</span><span class="p">)</span>
         <span class="p">(</span><span class="s">"C-c r r"</span> <span class="o">.</span> <span class="nv">consult-ripgrep</span><span class="p">)</span>
         <span class="p">(</span><span class="s">"C-c g g"</span> <span class="o">.</span> <span class="nv">consult-git-grep</span><span class="p">)</span>
         <span class="p">(</span><span class="s">"C-c f l"</span> <span class="o">.</span> <span class="nv">consult-focus-lines</span><span class="p">)))</span>
</code></pre></div></div>

<p>You will not regret it.</p>

<p>Then, in your <code class="language-plaintext highlighter-rouge">squint</code> little package, replace <code class="language-plaintext highlighter-rouge">completing-read</code> with
<code class="language-plaintext highlighter-rouge">consult--read</code>. Let’s see how.</p>

<h4 id="consultread">consult–read</h4>
<p>To break the ice, I suggest you to experiment with the following:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">consult--read</span>
 <span class="o">'</span><span class="p">(</span><span class="s">"arsenic"</span> <span class="s">"digitalis"</span> <span class="s">"strychnine"</span> <span class="s">"belladonna"</span><span class="p">)</span>
 <span class="ss">:prompt</span> <span class="s">"Choose your poison: "</span>
 <span class="ss">:state</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">action</span> <span class="nv">candidate</span><span class="p">)</span>
          <span class="p">(</span><span class="nv">pcase</span> <span class="nv">action</span>
            <span class="p">(</span><span class="ss">'preview</span> <span class="p">(</span><span class="nv">message</span> <span class="s">"preview: %s"</span> <span class="nv">candidate</span><span class="p">))</span>
            <span class="p">(</span><span class="ss">'return</span> <span class="p">(</span><span class="k">if</span> <span class="nv">candidate</span>
                         <span class="p">(</span><span class="nv">message</span> <span class="s">"return: %s"</span> <span class="nv">candidate</span><span class="p">)</span>
                       <span class="p">(</span><span class="nv">message</span> <span class="s">"return: Nothing"</span><span class="p">))))))</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">consult--read</code> is a bit more complex than <code class="language-plaintext highlighter-rouge">completing-read</code>, but for
our goal it should suffice to know the following:</p>

<ul>
  <li>
    <p>Remember that <code class="language-plaintext highlighter-rouge">completing-read</code> happily worked with lists of
strings, lists of symbols or even alists? Well, <code class="language-plaintext highlighter-rouge">consult--read</code> is
slightly pickier, as it does not like lists of symbols. Curiously,
it accepts association lists whose keys are symbols. So, you can
keep feeding it with <code class="language-plaintext highlighter-rouge">squint-heights</code> as the list of candidates,
just like you used to to with <code class="language-plaintext highlighter-rouge">completing-read</code>.</p>
  </li>
  <li>
    <p>Just like <code class="language-plaintext highlighter-rouge">completing-read</code>, after the candidate has been chosen, it
returns the selected key as a string.</p>
  </li>
  <li>
    <p>For any action performed by the user, the lambda function defined
at <code class="language-plaintext highlighter-rouge">:state</code> is invoked, with 2 arguments: <code class="language-plaintext highlighter-rouge">action</code>, and <code class="language-plaintext highlighter-rouge">candidate</code>.</p>
  </li>
</ul>

<p>This lambda requires a bit of explanation.<br />
It is invoked during several stages of the execution. The argument
<code class="language-plaintext highlighter-rouge">action</code> specifies which. The value of <code class="language-plaintext highlighter-rouge">candidate</code> indicates the
selected candidate, or <code class="language-plaintext highlighter-rouge">nil</code> if no candidate matches or if the user
decided to cancel. Or in few other cases. And this makes things a bit
hairy.<br />
In practice, just know that the couple of <code class="language-plaintext highlighter-rouge">action</code> / <code class="language-plaintext highlighter-rouge">candidate</code> shall
be interpreted as follows:</p>

<table>
  <thead>
    <tr>
      <th>Value of <code class="language-plaintext highlighter-rouge">action</code></th>
      <th>Value of <code class="language-plaintext highlighter-rouge">candidate</code></th>
      <th>Meaning</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">setup</code></td>
      <td><code class="language-plaintext highlighter-rouge">nil</code></td>
      <td><code class="language-plaintext highlighter-rouge">consult--read</code> has just been invoked.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">preview</code></td>
      <td>some candidate</td>
      <td>The user focused on a candidate.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">preview</code></td>
      <td><code class="language-plaintext highlighter-rouge">nil</code></td>
      <td>The user either typed something not matching any candidate, or completed the operation.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">exit</code></td>
      <td><code class="language-plaintext highlighter-rouge">nil</code></td>
      <td><code class="language-plaintext highlighter-rouge">cosult--read</code> is preparing to close the minibuffer.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">return</code></td>
      <td>some candidate</td>
      <td>The user confirmed with a valid candidate.</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">return</code></td>
      <td><code class="language-plaintext highlighter-rouge">nil</code></td>
      <td>The user quit, without selecting a valid candidate.</td>
    </tr>
  </tbody>
</table>

<p>I might be wrong, but although I think consult is a masterpiece, I
would have prefered <code class="language-plaintext highlighter-rouge">consult--read</code> to be a bit more
straightforward. Indeed, I find it a bit confusing.<br />
Play with the example I provided above, keeping the <code class="language-plaintext highlighter-rouge">*Messages*</code>
buffer open (<code class="language-plaintext highlighter-rouge">M-x view-echo-area-messages</code> or <code class="language-plaintext highlighter-rouge">C-h e</code>) and notice the
following:</p>

<ul>
  <li>
    <p>As you select a candidate, the lambda is invoked passing <code class="language-plaintext highlighter-rouge">preview</code>
as the action and the candidate name. This is what we will use to
preview the selected <code class="language-plaintext highlighter-rouge">squint-height</code>.</p>
  </li>
  <li>
    <p>When you confirm the selection:</p>

    <ul>
      <li><code class="language-plaintext highlighter-rouge">preview</code> is invoked a last time, with <code class="language-plaintext highlighter-rouge">nil</code> as the
candidate. What the hell?</li>
      <li>Luckily, <code class="language-plaintext highlighter-rouge">return</code> is also invoked, with the selected
candidate. Nice, it’s likely we will use this for the final
selection.</li>
    </ul>
  </li>
  <li>
    <p>Now, try to cancel the selection, using <code class="language-plaintext highlighter-rouge">C-g</code>:</p>

    <ul>
      <li>Also in this case, <code class="language-plaintext highlighter-rouge">preview</code> is invoked a last time, with <code class="language-plaintext highlighter-rouge">nil</code> as
the candidate. It’s likely that we will need to workaround those
funny empty calls.</li>
      <li>Also in this case, <code class="language-plaintext highlighter-rouge">return</code> is finally invoked. This time, though,
with <code class="language-plaintext highlighter-rouge">nil</code> as the candidate.</li>
    </ul>
  </li>
  <li>
    <p>Finally, try inputing garbage so that no candidate matches:</p>

    <ul>
      <li>You will see the very same behavior as for legit candidates. This
is also confusing.</li>
    </ul>
  </li>
</ul>

<p>A convenient option that helps handling some cases is <code class="language-plaintext highlighter-rouge">:require-match
t</code>, which prevents the user from confirming the selection with a
non-existing candidates. Unfortunately for our goals, <code class="language-plaintext highlighter-rouge">preview</code> is
still invoked passing non-matching candidtes. Try yourself:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nv">consult--read</span>
 <span class="o">'</span><span class="p">(</span><span class="s">"arsenic"</span> <span class="s">"digitalis"</span> <span class="s">"strychnine"</span> <span class="s">"belladonna"</span><span class="p">)</span>
 <span class="ss">:prompt</span> <span class="s">"Choose your poison: "</span>
 <span class="ss">:require-match</span> <span class="no">t</span>
 <span class="ss">:state</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">action</span> <span class="nv">candidate</span><span class="p">)</span>
          <span class="p">(</span><span class="nv">pcase</span> <span class="nv">action</span>
            <span class="p">(</span><span class="ss">'preview</span> <span class="p">(</span><span class="nv">message</span> <span class="s">"preview: %s"</span> <span class="nv">candidate</span><span class="p">))</span>
            <span class="p">(</span><span class="ss">'return</span> <span class="p">(</span><span class="k">if</span> <span class="nv">candidate</span>
                         <span class="p">(</span><span class="nv">message</span> <span class="s">"return: %s"</span> <span class="nv">candidate</span><span class="p">)</span>
                       <span class="p">(</span><span class="nv">message</span> <span class="s">"return: Nothing"</span><span class="p">))))))</span>
</code></pre></div></div>

<p>In conclusion: it seems that for the <code class="language-plaintext highlighter-rouge">preview</code> case we have to
manually make sure that the input candidate is actually one of the
valid choises. Since the candidate list <code class="language-plaintext highlighter-rouge">squint-heights</code> is an
association list, we could use <code class="language-plaintext highlighter-rouge">(assq key alist)</code>, a function
returning the key/value pair if <code class="language-plaintext highlighter-rouge">key</code> is a key in <code class="language-plaintext highlighter-rouge">alist</code>, <code class="language-plaintext highlighter-rouge">nil</code>
otherwise. This leads us to:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>
        
<span class="p">(</span><span class="nv">consult--read</span>
 <span class="nv">squint-heights</span>
 <span class="ss">:prompt</span> <span class="s">"Choose your poison: "</span>
 <span class="ss">:require-match</span> <span class="no">t</span>
 <span class="ss">:state</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">action</span> <span class="nv">candidate</span><span class="p">)</span>
          <span class="p">(</span><span class="nv">pcase</span> <span class="nv">action</span>
            <span class="p">(</span><span class="ss">'preview</span> 
                <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nv">assq</span> <span class="p">(</span><span class="nb">intern</span> <span class="nv">candidate</span><span class="p">)</span> <span class="nv">squint-heights</span><span class="p">)</span>
                  <span class="p">(</span><span class="nv">message</span> <span class="s">"preview: %s"</span> <span class="nv">candidate</span><span class="p">)</span>
                  <span class="p">(</span><span class="nv">message</span> <span class="s">"Nothing to preview"</span><span class="p">)))</span>
            <span class="p">(</span><span class="ss">'return</span> <span class="p">(</span><span class="k">if</span> <span class="nv">candidate</span>
                         <span class="p">(</span><span class="nv">message</span> <span class="s">"return: %s"</span> <span class="nv">candidate</span><span class="p">)</span>
                       <span class="p">(</span><span class="nv">message</span> <span class="s">"return: Nothing"</span><span class="p">))))))</span>
</code></pre></div></div>

<p>An alternative could be to get the height directly, with out
<code class="language-plaintext highlighter-rouge">squint--height-from-label</code>, then combining the definition of a
variable and an if/then/else clause with <code class="language-plaintext highlighter-rouge">if-let</code>:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">consult--read</span>
 <span class="nv">squint-heights</span>
 <span class="ss">:prompt</span> <span class="s">"Choose your poison: "</span>
 <span class="ss">:require-match</span> <span class="no">t</span>
 <span class="ss">:state</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">action</span> <span class="nv">candidate</span><span class="p">)</span>
          <span class="p">(</span><span class="nv">pcase</span> <span class="nv">action</span>
            <span class="p">(</span><span class="ss">'preview</span> 
                <span class="p">(</span><span class="nv">if-let</span> <span class="p">(</span><span class="nv">height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="nv">candidate</span><span class="p">))</span>
                  <span class="p">(</span><span class="nv">message</span> <span class="s">"selected: %s, previewing with height: %s"</span> <span class="nv">candidate</span> <span class="nv">height</span><span class="p">)</span>
                  <span class="p">(</span><span class="nv">message</span> <span class="s">"Nothing to preview"</span><span class="p">)))</span>
            <span class="p">(</span><span class="ss">'return</span> <span class="p">(</span><span class="k">if</span> <span class="nv">candidate</span>
                         <span class="p">(</span><span class="nv">message</span> <span class="s">"return: %s"</span> <span class="nv">candidate</span><span class="p">)</span>
                       <span class="p">(</span><span class="nv">message</span> <span class="s">"return: Nothing"</span><span class="p">))))))</span>
</code></pre></div></div>

<p>Cool. It seems to work.<br />
By the way, having obtained a <code class="language-plaintext highlighter-rouge">height</code> already at this point will
allow us to use <code class="language-plaintext highlighter-rouge">squint--set-height</code> directly, getting rid of the
<code class="language-plaintext highlighter-rouge">squint--set-height-from-label</code> helper function.</p>

<p>Let’s keep on analyzing. Remember that <code class="language-plaintext highlighter-rouge">preview</code> is being called a
last time, with a <code class="language-plaintext highlighter-rouge">nil</code> candidate? That’s the case when we don’t need
to preview anything. We’d better replace the <code class="language-plaintext highlighter-rouge">if-let</code> case:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>                <span class="p">(</span><span class="nv">if-let</span> <span class="p">(</span><span class="nv">height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="nv">candidate</span><span class="p">))</span>
                  <span class="p">(</span><span class="nv">message</span> <span class="s">"selected: %s, previewing with height: %s"</span> <span class="nv">candidate</span> <span class="nv">height</span><span class="p">)</span>
                  <span class="p">(</span><span class="nv">message</span> <span class="s">"Nothing to preview"</span><span class="p">))</span><span class="err">)</span>
</code></pre></div></div>

<p>with <code class="language-plaintext highlighter-rouge">when-let</code>, which does the same of <code class="language-plaintext highlighter-rouge">if-let</code>, without an else leg:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>                <span class="p">(</span><span class="nv">when-let</span> <span class="p">(</span><span class="nv">height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="nv">candidate</span><span class="p">))</span>
                  <span class="p">(</span><span class="nv">message</span> <span class="s">"selected: %s, previewing with height: %s"</span> <span class="nv">candidate</span> <span class="nv">height</span><span class="p">))</span><span class="err">)</span>
</code></pre></div></div>

<h5 id="reset">Reset</h5>
<p>We are almost done. We just need to cover the <code class="language-plaintext highlighter-rouge">return</code>
case.</p>

<p>Think about this: we will preview the selected height by invoking our
<code class="language-plaintext highlighter-rouge">squint--set-height</code>: by itself, this is a destructive operation. I
mean, although the intention is only to <em>preview</em> the new height,
there is no magic way to ask Emcs “I joked: undo what you just
did”. Most likely, instead, we will need to keep track of the initial
face height, and to invoke <code class="language-plaintext highlighter-rouge">squint--set-height</code> with that value, if
the user cancels.</p>

<p>So:</p>

<ul>
  <li>If the user confirms the selection, we do nothing: we can keep the
already previewed face height.</li>
  <li>If the user cancels, we need to reset the height to the initial one.</li>
</ul>

<p>This all means that we definitely need to store the initial height
somewhere before invoking <code class="language-plaintext highlighter-rouge">consult--read</code>. We could either use a
global variable, or a local variable, which we can conveniently
capture in a closure.</p>

<p>Let’s play with a closure. Here’s a possible approach:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">previous-height</span> <span class="p">(</span><span class="nv">face-attribute</span> <span class="ss">'default</span> <span class="ss">:height</span><span class="p">)))</span>

  <span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--reset-height</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">message</span> <span class="s">"%s"</span> <span class="nv">previous-height</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">squint--set-height</span> <span class="mi">180</span><span class="p">))</span>

  <span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">consult--read</span>
     <span class="nv">squint-heights</span>
     <span class="ss">:prompt</span> <span class="s">"Choose your poison: "</span>
     <span class="ss">:require-match</span> <span class="no">t</span>
     <span class="ss">:state</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">action</span> <span class="nv">candidate</span><span class="p">)</span>
              <span class="p">(</span><span class="nv">pcase</span> <span class="nv">action</span>
                <span class="p">(</span><span class="ss">'preview</span> <span class="p">(</span><span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="nv">candidate</span><span class="p">)))</span>
                <span class="p">(</span><span class="ss">'return</span> <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">null</span> <span class="nv">candidate</span><span class="p">)</span>
                             <span class="p">(</span><span class="nv">squint--reset-height</span><span class="p">))))))))</span>
</code></pre></div></div>

<p>For closures to work as you expect, <a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html">Lexical Binding</a>
must be active. You ither need to add:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; -*- lexical-binding: t -*-</span>
</code></pre></div></div>

<p>as th very first line of your file, or to set:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">lexical-binding</span> <span class="no">t</span><span class="p">)</span>
</code></pre></div></div>

<p>You probably like to have a little explanation here. Let’s see.</p>

<h4 id="dynamic-and-lexical-binding">Dynamic and Lexical Binding</h4>
<p>Consider this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; -*- lexical-binding: t -*-</span>

<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">v</span> <span class="s">"captured value"</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">defun</span> <span class="nv">run-me</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">message</span> <span class="s">"v = %s"</span> <span class="nv">v</span><span class="p">)))</span>
</code></pre></div></div>

<p>It first defines a variable <code class="language-plaintext highlighter-rouge">v</code> with some value. <code class="language-plaintext highlighter-rouge">v</code> is not a global
variable; it only exists in the scope defined by its <code class="language-plaintext highlighter-rouge">let</code>, so
basically in the 2 lines under <code class="language-plaintext highlighter-rouge">let</code> itself.</p>

<p>Inside that scope, a function <code class="language-plaintext highlighter-rouge">run-me</code> is defined. Notice that
<code class="language-plaintext highlighter-rouge">run-me</code>’s body makes use of <code class="language-plaintext highlighter-rouge">v</code>, and that <code class="language-plaintext highlighter-rouge">v</code> itself, from the
<code class="language-plaintext highlighter-rouge">run-me</code> function standpoint, is defined in the outer scope.</p>

<p>We say that <code class="language-plaintext highlighter-rouge">run-me</code> captures <code class="language-plaintext highlighter-rouge">v</code> from its surrounding scope.</p>

<p>Now: you know that local variables are accessible only from within the
scope they are defined. So, the following does not work:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; -*- lexical-binding: t -*-</span>

<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">v</span> <span class="s">"captured value"</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">defun</span> <span class="nv">run-me</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">message</span> <span class="s">"v = %s"</span> <span class="nv">v</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">message</span> <span class="s">"Do we have a v here? v = %s"</span> <span class="nv">v</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">v</code> does not exist outside its <code class="language-plaintext highlighter-rouge">let</code> scope.<br />
Interestingly, though, this works:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; -*- lexical-binding: t -*-</span>

<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">v</span> <span class="s">"captured value"</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">defun</span> <span class="nv">run-me</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">message</span> <span class="s">"v = %s"</span> <span class="nv">v</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">run-me</span><span class="p">)</span> <span class="c1">;; v = captured value</span>
</code></pre></div></div>

<p>This works because, as we said, <code class="language-plaintext highlighter-rouge">run-me</code> <em>captured</em> the variable
<code class="language-plaintext highlighter-rouge">v</code>. In other words, <code class="language-plaintext highlighter-rouge">run-me</code> keeps a reference to the scope it was
created in, so that scope does not die when the <code class="language-plaintext highlighter-rouge">let</code> expression
finishes its execution.<br />
This is basically the idea of <em>closures</em>.</p>

<p>Now, consider this slightly different version:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; -*- lexical-binding: t -*-</span>

<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">v</span> <span class="s">"captured value"</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">defun</span> <span class="nv">run-me</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">message</span> <span class="s">"v = %s"</span> <span class="nv">v</span><span class="p">)))</span>

<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">v</span> <span class="s">"some other value"</span><span class="p">))</span>
  <span class="p">(</span><span class="nv">run-me</span><span class="p">))</span>
</code></pre></div></div>

<p>Not surprisingly, the last expression still emits <code class="language-plaintext highlighter-rouge">v = captured
value</code>.</p>

<p>In fact: we are creating another, separate variable <code class="language-plaintext highlighter-rouge">v</code>, with a
different value. When <code class="language-plaintext highlighter-rouge">run-me</code> is evaluated, though, it still
reference its own <code class="language-plaintext highlighter-rouge">v</code>. Although sharing the same name, the two <code class="language-plaintext highlighter-rouge">v</code>
variables exist and live in separate, independent scopes. Which scope
a specific piece of code is using can be easily determined by looking
at <em>where</em> it is defined in the code structure: in other
words, it can inferred from their <em>lexical context</em>.<br />
This behavior is called <em>lexical binding</em>.</p>

<p>Emacs also supports <em>dynamic binding</em>. See the difference:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">v</span> <span class="s">"captured value"</span><span class="p">))</span>
  <span class="p">(</span><span class="nb">defun</span> <span class="nv">run-me</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">message</span> <span class="s">"v = %s"</span> <span class="nv">v</span><span class="p">)))</span>

<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">v</span> <span class="s">"some other value"</span><span class="p">))</span>
  <span class="p">(</span><span class="nv">run-me</span><span class="p">))</span>
</code></pre></div></div>

<p>Notice that I removed the:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; -*- lexical-binding: t -*-</span>
</code></pre></div></div>

<p>I could even enabled explicitly the dynamic binding with <code class="language-plaintext highlighter-rouge">(setq
lexical-scope nil)</code>.</p>

<p>Surprisingly, now the last expression emits <code class="language-plaintext highlighter-rouge">some other value</code>.</p>

<p>In Dynamic Binding, variables are resolved based on the <em>runtime
environment</em> rather than on the <em>definition-time environment</em>.<br />
When <code class="language-plaintext highlighter-rouge">run-me</code> is defined, it doesn’t <em>capture</em> <code class="language-plaintext highlighter-rouge">v</code>. Instead, it just
remembers that it needs to use a variable named <code class="language-plaintext highlighter-rouge">v</code>.<br />
When finally <code class="language-plaintext highlighter-rouge">run-me</code> is invoked, it looks for the current value of
<code class="language-plaintext highlighter-rouge">v</code> <em>in the caller scope</em>, at run-time. It finds a <code class="language-plaintext highlighter-rouge">v</code> set to <code class="language-plaintext highlighter-rouge">some
other value</code>, and it uses it.</p>

<p>You will find very few languages supporting this style. You can learn
more on this reading <a href="https://www.emacswiki.org/emacs/LexicalBinding">Lexical Binding</a> in the
Emacs Wiki.</p>

<p>So, here’s the code we ended up with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">;; -*- lexical-binding: t -*-</span>

<span class="p">(</span><span class="k">setq</span> <span class="nv">squint-heights</span>
      <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">100</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--height-from-label</span> <span class="p">(</span><span class="nv">label</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">alist-get</span> <span class="p">(</span><span class="nb">intern</span> <span class="nv">label</span><span class="p">)</span> <span class="nv">squint-heights</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">height</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">set-face-attribute</span> <span class="ss">'default</span> <span class="no">nil</span> <span class="ss">:height</span> <span class="nv">height</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--get-labels</span> <span class="p">(</span><span class="nv">squint-heights</span><span class="p">)</span>
  <span class="s">"Return a list of string labels from squint-heights."</span>
  <span class="p">(</span><span class="nb">mapcar</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">pair</span><span class="p">)</span> <span class="p">(</span><span class="nb">symbol-name</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">pair</span><span class="p">)))</span>
          <span class="nv">squint-heights</span><span class="p">))</span>

<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">previous-height</span> <span class="p">(</span><span class="nv">face-attribute</span> <span class="ss">'default</span> <span class="ss">:height</span><span class="p">)))</span>

  <span class="p">(</span><span class="nb">defun</span> <span class="nv">squint--reset-height</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">message</span> <span class="s">"%s"</span> <span class="nv">previous-height</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">squint--set-height</span> <span class="mi">180</span><span class="p">))</span>

  <span class="p">(</span><span class="nb">defun</span> <span class="nv">squint</span> <span class="p">()</span>
    <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
    <span class="p">(</span><span class="nv">consult--read</span>
     <span class="nv">squint-heights</span>
     <span class="ss">:prompt</span> <span class="s">"Choose your poison: "</span>
     <span class="ss">:require-match</span> <span class="no">t</span>
     <span class="ss">:state</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">action</span> <span class="nv">candidate</span><span class="p">)</span>
              <span class="p">(</span><span class="nv">pcase</span> <span class="nv">action</span>
                <span class="p">(</span><span class="ss">'preview</span> <span class="p">(</span><span class="nv">squint--set-height</span> <span class="p">(</span><span class="nv">squint--height-from-label</span> <span class="nv">candidate</span><span class="p">)))</span>
                <span class="p">(</span><span class="ss">'return</span> <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">null</span> <span class="nv">candidate</span><span class="p">)</span>
                             <span class="p">(</span><span class="nv">squint--reset-height</span><span class="p">))))))))</span>
</code></pre></div></div>

<p>Evaluate it, and you will have your beautiful <code class="language-plaintext highlighter-rouge">squint</code> command at
hand.</p>

<h3 id="step-6---make-it-a-package">Step 6 - Make it a package</h3>

<p>It would be nice to have <code class="language-plaintext highlighter-rouge">squint</code> loaded when Emacs starts. I’m also
sure that, as you get better and better with Lisp, you will improve
this little function making it so beautiful that every single Emacs
user in the world will want to use it. Eventually, you will need to
publish it on Melpa, and it will overtake Magit’s monthly downloads.</p>

<p>So, you need to make it a package.<br />
This is indeed a very easy task.</p>

<p>First, add a very last line declaring that the file <em>provides</em> a
package:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">provide</span> <span class="ss">'squint</span><span class="p">)</span>
</code></pre></div></div>

<p>Second, make sure that the package name (<code class="language-plaintext highlighter-rouge">squint</code>) is consistent with
the file name (<code class="language-plaintext highlighter-rouge">squint.el</code>).</p>

<p>Finally, store the file in one of the directories Emacs parses when it
looks for packages. Inspect the variable <code class="language-plaintext highlighter-rouge">load-path</code> to know which
ones (<code class="language-plaintext highlighter-rouge">M-x describe-variable RET load-path RET</code>).<br />
In my case I get a huge list like this:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="s">"/usr/share/emacs/site-lisp/"</span>
 <span class="s">"~/.config/emacs/local-packages"</span>
 
 <span class="s">"/home/arialdo/.config/emacs/elpa/ag-20201031.2202"</span>
 <span class="s">"/home/arialdo/.config/emacs/elpa/aggressive-indent-20230112.1300"</span>
 <span class="s">"/home/arialdo/.config/emacs/elpa/auto-hide"</span>
 <span class="s">"/home/arialdo/.config/emacs/elpa/avy-20230420.404"</span>
 <span class="s">"/home/arialdo/.config/emacs/elpa/buffer-expose-0.4.3"</span>
 <span class="s">"/home/arialdo/.config/emacs/elpa/corfu-20241030.1005"</span>
 <span class="o">...</span>
 <span class="s">"/usr/share/emacs/31.0.50/site-lisp"</span>
 <span class="s">"/usr/share/emacs/site-lisp"</span>
 <span class="s">"/usr/share/emacs/31.0.50/lisp"</span>
 <span class="s">"/usr/share/emacs/31.0.50/lisp/vc"</span>
 <span class="s">"/usr/share/emacs/31.0.50/lisp/use-package"</span>
 <span class="s">"/usr/share/emacs/31.0.50/lisp/url"</span>
 <span class="s">"/usr/share/emacs/31.0.50/lisp/textmodes"</span>
 <span class="s">"/usr/share/emacs/31.0.50/lisp/progmodes"</span>
 <span class="o">...</span>
 <span class="s">"/usr/share/emacs/31.0.50/lisp/calc"</span>
 <span class="s">"/usr/share/emacs/31.0.50/lisp/obsolete"</span><span class="p">)</span>
</code></pre></div></div>

<p>Notice the second item: <code class="language-plaintext highlighter-rouge">"~/.config/emacs/local-packages"</code>: this is a
custom directory I created for my personal packages. here’s what
you need to do:</p>

<ul>
  <li>Create a directory in your home or in the standard XDG directory
(<code class="language-plaintext highlighter-rouge">~/.config/emacs</code>) where to keep your personal packages.</li>
  <li>Then, in your init file, instruct Emacs to add this directory to the
list of directories to search in:</li>
</ul>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>  <span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">'load-path</span> <span class="s">"&lt;YOUR_DIRECTORY_HERE"</span><span class="p">)</span>
</code></pre></div></div>

<p>That’s it. Now you can load <code class="language-plaintext highlighter-rouge">squint</code> with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">require</span> <span class="ss">'squint</span><span class="p">)</span>
</code></pre></div></div>

<p>If you prefer <code class="language-plaintext highlighter-rouge">use-package</code> like I do, go with:</p>

<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">use-package</span> <span class="nv">squint</span>
  <span class="ss">:ensure</span> <span class="no">nil</span>
  <span class="ss">:custom</span>
  <span class="p">(</span><span class="nv">squint-heights</span> <span class="o">'</span><span class="p">((</span><span class="nv">office</span> <span class="o">.</span> <span class="mi">1000</span><span class="p">)</span>
                    <span class="p">(</span><span class="nv">laptop</span> <span class="o">.</span> <span class="mi">180</span><span class="p">)</span>
                    <span class="p">(</span><span class="nv">programming</span> <span class="o">.</span> <span class="mi">190</span><span class="p">)</span>
                    <span class="p">(</span><span class="nv">presentation</span> <span class="o">.</span> <span class="mi">200</span><span class="p">)))</span>
  <span class="ss">:bind</span> <span class="p">(</span><span class="s">"C-c s q"</span> <span class="o">.</span> <span class="nv">squint</span><span class="p">))</span>
</code></pre></div></div>

<p>Never mind that your code already contains a definition for
<code class="language-plaintext highlighter-rouge">squint-heights</code>: <code class="language-plaintext highlighter-rouge">use-package</code> is smart enough to use the value
you provide in <code class="language-plaintext highlighter-rouge">:custom</code>.</p>

<p>Cool! Your first package!<br />
Of course, there would be so much to add and study about packages
— such as how to write a proper documentation, how to declare
dependencies on other packages and the like. But you can be proud of
yourself already, can’t you?</p>

<h2 id="where-to-go-from-here">Where to go from here?</h2>
<p>Why should <code class="language-plaintext highlighter-rouge">squint</code> work with font heights only? Why not to have
presets for any arbitrary face attribute?<br />
The scaffold is set up: you will not find hard to extend what you
wrote so far.</p>

<p>If you want to get inspiration and to learn from a real master, go
checkout <a href="https://protesilaos.com/emacs/fontaine">Fontaine</a>, by <a href="https://protesilaos.com/">Protesilaos</a>. It does exactly
that.<br />
In fact, this post is an elaboration of what I learnt from some lessons
I got from him, as I wanted to better understand how his packages work.</p>

<p>That’s all. Take care. Happy lisping!</p>

<h1 id="references">References</h1>

<ul>
  <li>Emacs Manual
    <ul>
      <li><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Text-Scale.html">Text Scale</a></li>
      <li><a href="https://www.gnu.org/software/emacs/manual/html_node/emacs/Faces.html">Faces</a></li>
      <li><a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Association-Lists.html">Association Lists</a></li>
      <li><a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Symbols.html">Symbols</a></li>
      <li><a href="https://www.gnu.org/software/emacs/manual/html_node/elisp/Lexical-Binding.html">Lexical Binding</a>
        <ul>
          <li><a href="https://www.emacswiki.org/emacs/LexicalBinding">Lexical Binding - Wiki</a></li>
        </ul>
      </li>
    </ul>
  </li>
  <li><a href="https://github.com/minad/consult">consult</a></li>
  <li><a href="https://protesilaos.com/emacs/fontaine">Fontaine</a></li>
  <li><a href="https://protesilaos.com/">Protesilaos Stavrou</a></li>
</ul>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="emacs" /><category term="lisp" /><summary type="html"><![CDATA[Let’s develop squint a little package for controlling the font height, so you won’t need to squint your eyes when you are on smaller screens. It will look like this: It will give us the chance to touch on: Face attributes. Asking the user to choose interactively from a list of options. The powerful consult--read. Lisp’s Dynamic and Lexical Binding. Few other little topics here and there.]]></summary></entry><entry><title type="html">State Monad For The Rest Of Us - Part 1</title><link href="http://arialdomartini.github.io/state-monad-for-the-rest-of-us-1" rel="alternate" type="text/html" title="State Monad For The Rest Of Us - Part 1" /><published>2024-07-01T00:00:00+00:00</published><updated>2024-07-01T00:00:00+00:00</updated><id>http://arialdomartini.github.io/state-monad-for-the-rest-of-us-1</id><content type="html" xml:base="http://arialdomartini.github.io/state-monad-for-the-rest-of-us-1"><![CDATA[<p><a href="state-monad-for-the-rest-of-us">Index</a><br />
Source code:
<a href="https://github.com/arialdomartini/state-monad-for-the-rest-of-us">github.com/arialdomartini/state-monad-for-the-rest-of-us</a></p>

<h2 id="binary-trees">Binary Trees</h2>

<p>Our journey starts with this problem: we want to count the number of
leaves of an arbitrary Binary Tree. To keep the problem as simple as
possible, we define a Binary Tree as that data structure having Nodes
and Leaves, and in which every Node has exactly two branches.</p>

<p>This is a Tree with 2 Leaves:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     Node
     /  \
  Leaf  Leaf
</code></pre></div></div>

<p>and here is a Tree with 3 Leaves:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     Node
     /  \
  Leaf  Node
        /  \
    Leaf   Leaf
</code></pre></div></div>

<p>It is legit to ask ourselves: is a single Leaf a Tree?</p>

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

<p>Let’s agree that it is.<br />
Do null Trees — Trees without Nodes and Leaves — exist?<br />
Let’s do ourselves a favor and agree they don’t.</p>

<p>A Node always contains 2 Leaves. What does a Leaf contain? Nothing: it
just is.<br />
So, a Tree is either a Leaf or a Node made of 2 branches, each
containing another Tree structure. Remember this definition, because
we will translate it more or less literally to F#.</p>

<p>How deep can such Binary Trees be? Arbitrarily deep. For example, this
is a legit Tree:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     Node
     /  \
  Leaf  Node
        /  \
     Node   Leaf
     /  \
  Leaf  Node
        /  \
      Node  Leaf
      /  \
  Leaf   Node
         /  \
      Leaf  Leaf
</code></pre></div></div>

<p>Of course, our code should work with any Tree, no matter how deep.</p>

<h2 id="counting-leaves">Counting Leaves</h2>
<p>Good. We are diligent developers, so we start from a test. To keep it
simple, let’s count the Leaves of a 3-leaves Tree:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">module</span> <span class="nc">StateMonadTest</span>

<span class="k">open</span> <span class="nc">Xunit</span>
<span class="k">open</span> <span class="nn">Swensen</span><span class="p">.</span><span class="nc">Unquote</span>

<span class="k">let</span> <span class="n">numberOfLeaves</span> <span class="n">tree</span> <span class="p">=</span> <span class="n">failwith</span> <span class="s2">"Not yet implemented"</span>

<span class="p">[&lt;</span><span class="nc">Fact</span><span class="p">&gt;]</span>
<span class="k">let</span> <span class="n">``counts the number of leaves in a tree``</span> <span class="bp">()</span> <span class="p">=</span>
    <span class="k">let</span> <span class="n">treeWith3Leaves</span> <span class="p">=</span> <span class="n">failwith</span> <span class="s2">"Not yet implemented"</span>
    
    <span class="k">let</span> <span class="n">leaves</span> <span class="p">=</span> <span class="n">numberOfLeaves</span> <span class="n">treeWith3Leaves</span>
    
    <span class="n">test</span> <span class="o">&lt;@</span> <span class="n">leaves</span> <span class="p">=</span> <span class="mi">3</span> <span class="o">@&gt;</span>
</code></pre></div></div>

<p>Let’s fill the gaps. As often happens with Functional Programming, it
is convenient to start from modeling problems through their types.</p>

<h2 id="sum-and-product-types">Sum and Product Types</h2>
<p>How to model a Tree?
That’s an easy task in F#: it’s a matter of translating literally our
definition:</p>

<blockquote>
  <p>A Tree is 
either a Leaf 
or a Node containing 2 branches
each containing another Tree structure.</p>
</blockquote>

<p>Step by step:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">A Tree is</code> is simply translated to</li>
</ul>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">Tree</span> <span class="p">=</span>
</code></pre></div></div>

<ul>
  <li>A Tree can <code class="language-plaintext highlighter-rouge">be a Leaf</code>:</li>
</ul>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">Tree</span> <span class="p">=</span> <span class="nc">Leaf</span>
</code></pre></div></div>

<ul>
  <li><code class="language-plaintext highlighter-rouge">or a Node</code>. The <code class="language-plaintext highlighter-rouge">or</code> part is translated with the <code class="language-plaintext highlighter-rouge">|</code> operator:</li>
</ul>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">Tree</span> <span class="p">=</span> <span class="nc">Leaf</span> <span class="p">|</span> <span class="nc">Node</span> <span class="o">???</span>
</code></pre></div></div>

<ul>
  <li>The Node <code class="language-plaintext highlighter-rouge">contains</code> <code class="language-plaintext highlighter-rouge">2</code> branches. The <em>contain</em> part is translated with
<code class="language-plaintext highlighter-rouge">of</code>, the multiplicity is translated with <code class="language-plaintext highlighter-rouge">*</code>:</li>
</ul>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">Tree</span> <span class="p">=</span> <span class="nc">Leaf</span> <span class="p">|</span> <span class="nc">Node</span> <span class="k">of</span> <span class="o">(???</span> <span class="p">*</span> <span class="o">???)</span>
</code></pre></div></div>

<ul>
  <li>We know that each branch contains either a Leaf or another Node. We
already have a type representing either a Leaf <em>or</em> a Node, dont’t
we? It’s the <code class="language-plaintext highlighter-rouge">Tree</code> itself. So:</li>
</ul>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">Tree</span> <span class="p">=</span> <span class="nc">Leaf</span> <span class="p">|</span> <span class="nc">Node</span> <span class="k">of</span> <span class="p">(</span><span class="nc">Tree</span> <span class="p">*</span> <span class="nc">Tree</span><span class="p">)</span>
</code></pre></div></div>

<p>That’s it!<br />
As an aside, this expression makes use of the so called Algebraic Data
Types, which include Sum (or Discriminated Union) Types and Product Types.</p>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Symbol used</th>
      <th>Equivalent technique in OOP</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Sum Types</td>
      <td><code class="language-plaintext highlighter-rouge">|</code></td>
      <td>Inheritance</td>
    </tr>
    <tr>
      <td>Product Types</td>
      <td><code class="language-plaintext highlighter-rouge">*</code></td>
      <td>Multiple fieds in classes</td>
    </tr>
  </tbody>
</table>

<p>In C# this would approximately translate to:</p>

<div class="language-csharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">abstract</span> <span class="n">record</span> <span class="n">Tree</span><span class="p">;</span>
<span class="n">record</span> <span class="n">Leaf</span> <span class="p">:</span> <span class="n">Tree</span><span class="p">;</span>
<span class="n">record</span> <span class="nf">Node</span><span class="p">(</span><span class="n">Tree</span> <span class="n">Left</span><span class="p">,</span> <span class="n">Tree</span> <span class="n">Right</span><span class="p">)</span> <span class="p">:</span> <span class="n">Tree</span><span class="p">;</span>
</code></pre></div></div>

<p>In both cases, we have a recursive type, which both languages happily support.</p>

<h2 id="creating-instances">Creating instances</h2>
<p>Creating instances in F# is similar, but more concise, than in C# and
Java: you just have to omit the <code class="language-plaintext highlighter-rouge">new</code> keyword and the parenthesis.
Our 3-leaves tree:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     Node
     /  \
  Leaf  Node
        /  \
    Leaf   Leaf
</code></pre></div></div>

<p>can be created with:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">treeWith3Leaves</span> <span class="p">=</span> <span class="nc">Node</span><span class="p">(</span><span class="nc">Leaf</span><span class="p">,</span> <span class="nc">Node</span><span class="p">(</span><span class="nc">Leaf</span><span class="p">,</span> <span class="nc">Leaf</span><span class="o">))</span>
</code></pre></div></div>

<p>This completes the test implementation:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[&lt;</span><span class="nc">Fact</span><span class="p">&gt;]</span>
<span class="k">let</span> <span class="n">``counts the number of leaves in a tree``</span> <span class="bp">()</span> <span class="p">=</span>
    <span class="k">let</span> <span class="n">treeWith3Leaves</span> <span class="p">=</span> <span class="nc">Node</span><span class="p">(</span><span class="nc">Leaf</span><span class="p">,</span> <span class="nc">Node</span><span class="p">(</span><span class="nc">Leaf</span><span class="p">,</span> <span class="nc">Leaf</span><span class="o">))</span>

    <span class="k">let</span> <span class="n">leaves</span> <span class="p">=</span> <span class="n">numberOfLeaves</span> <span class="n">treeWith3Leaves</span>

    <span class="n">test</span> <span class="o">&lt;@</span> <span class="n">leaves</span> <span class="p">=</span> <span class="mi">3</span> <span class="o">@&gt;</span>
</code></pre></div></div>

<p>Good. Now, let’s see how to make it green.</p>

<h2 id="type-constructors-and-data-constructors">Type Constructors and Data Constructors</h2>
<p>It is important to understand that in:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">Tree</span> <span class="p">=</span> <span class="nc">Leaf</span> <span class="p">|</span> <span class="nc">Node</span> <span class="k">of</span> <span class="p">(</span><span class="nc">Tree</span> <span class="p">*</span> <span class="nc">Tree</span><span class="p">)</span>
</code></pre></div></div>

<p><code class="language-plaintext highlighter-rouge">Tree</code> is a type, <code class="language-plaintext highlighter-rouge">Leaf</code> and <code class="language-plaintext highlighter-rouge">Node</code> are not: <code class="language-plaintext highlighter-rouge">Leaf</code> and <code class="language-plaintext highlighter-rouge">Node</code> are
ways for <em>creating</em> an instance of type <code class="language-plaintext highlighter-rouge">Tree</code>. This is akin to the
difference between a class and its constructors. In F#, we would call
<code class="language-plaintext highlighter-rouge">Tree</code>, <code class="language-plaintext highlighter-rouge">Leaf</code> and <code class="language-plaintext highlighter-rouge">Node</code>as follows:</p>

<table>
  <thead>
    <tr>
      <th>Element</th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Tree</code></td>
      <td>Discriminated Union Type</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Leaf</code> and <code class="language-plaintext highlighter-rouge">Node of (Tree * Tree)</code></td>
      <td>Union Case</td>
    </tr>
  </tbody>
</table>

<p>Haskell uses different names, but the meaning is the same:</p>

<table>
  <thead>
    <tr>
      <th>Element</th>
      <th>Name</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Tree</code></td>
      <td>Type Constructor</td>
    </tr>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Leaf</code> and <code class="language-plaintext highlighter-rouge">Node Tree Tree</code></td>
      <td>Data Constructor</td>
    </tr>
  </tbody>
</table>

<p>We will shortly see why <code class="language-plaintext highlighter-rouge">Tree</code> is a Type <em>Constructor</em>, not just a
Type: as soon as <code class="language-plaintext highlighter-rouge">Tree</code> will take a (type) parameter, we will learn to
see it more as a function than just a type name.</p>

<p>The takeaway here is: given an instance of <code class="language-plaintext highlighter-rouge">Tree</code>, F# can <em>pattern
match</em> on the Case which was used to create the instance. It’s like
the instance <em>remembers</em> which constructor was used to create it. You
can read more about it in <a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching#identifier-patterns">Pattern Matching - Identifier Patterns</a>.</p>

<p>This give you all the ingredients to develop a function to calculate
the number of leaves.</p>

<h2 id="implementation">Implementation</h2>
<p>Pattern matching is easy:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">numberOfLeaves</span> <span class="n">tree</span> <span class="p">=</span>
    <span class="k">match</span> <span class="n">tree</span> <span class="k">with</span>
    <span class="p">|</span> <span class="nc">Leaf</span> <span class="p">-&gt;</span> <span class="o">???</span>
    <span class="p">|</span> <span class="nc">Node</span> <span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="o">???</span> 
</code></pre></div></div>

<p>Read it as a glorified <code class="language-plaintext highlighter-rouge">if/then/else</code> and ask yourself:</p>

<ul>
  <li>If <code class="language-plaintext highlighter-rouge">numberOfLeaves</code> receives a tree, and that tree is a single
<code class="language-plaintext highlighter-rouge">Leaf</code>, how many leaves does that tree have? In other words, the
function needs to calculate the number of leaves of this tree:</li>
</ul>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>   Leaf
</code></pre></div></div>
<p>Of course, it has just <code class="language-plaintext highlighter-rouge">1</code> leaf! So:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="n">numberOfLeaves</span> <span class="n">tree</span> <span class="p">=</span>
    <span class="k">match</span> <span class="n">tree</span> <span class="k">with</span>
    <span class="p">|</span> <span class="nc">Leaf</span> <span class="p">-&gt;</span> <span class="mi">1</span>
    <span class="p">|</span> <span class="nc">Node</span> <span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="o">???</span> 
</code></pre></div></div>

<p>What about if <code class="language-plaintext highlighter-rouge">tree</code> is a <code class="language-plaintext highlighter-rouge">Node</code>? You only know that a <code class="language-plaintext highlighter-rouge">Node</code> contains
exactly <code class="language-plaintext highlighter-rouge">2</code> branches. Each branch could be a Leaf, like in:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     Node
     /  \
  Leaf  Leaf
</code></pre></div></div>

<p>or it could be another arbitrarily deep tree, like in:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     Node
     /  \
  Leaf  Node
        /  \
     Node   Leaf
     /  \
  Leaf  Node
        /  \
      Node  Leaf
      /  \
  Leaf   Node
         /  \
      Leaf  Leaf
</code></pre></div></div>

<p>In the general case, you can see the received tree as:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>     Node
     /  \
  Tree  Tree
</code></pre></div></div>

<p>This node contains as many leaves as the leaves in the right branch
tree, <em>plus</em> the leaves of the left branch tree. Literally translating
this sentence to F# leads us to:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="k">rec</span> <span class="n">numberOfLeaves</span> <span class="n">tree</span> <span class="p">=</span>
    <span class="k">match</span> <span class="n">tree</span> <span class="k">with</span>
    <span class="p">|</span> <span class="nc">Leaf</span> <span class="p">-&gt;</span> <span class="mi">1</span>
    <span class="p">|</span> <span class="nc">Node</span> <span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="n">numberOfLeaves</span> <span class="n">l</span> <span class="o">+</span> <span class="n">numberOfLeaves</span> <span class="n">r</span>
</code></pre></div></div>

<p>Notice that we added the keyword <code class="language-plaintext highlighter-rouge">rec</code> to the function definition, to
make it clear that the function is recursive.</p>

<p>Does this work? You have a test. Run it.<br />
Of course it’s green. As it often happens, if it compiles it works.
Get used to this, it will happen over and over.</p>

<h2 id="putting-all-together">Putting all together</h2>
<p>Let’s review what you obtained:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">Tree</span> <span class="p">=</span>
    <span class="p">|</span> <span class="nc">Leaf</span>
    <span class="p">|</span> <span class="nc">Node</span> <span class="k">of</span> <span class="nc">Tree</span> <span class="p">*</span> <span class="nc">Tree</span>

<span class="k">let</span> <span class="k">rec</span> <span class="n">numberOfLeaves</span> <span class="n">tree</span> <span class="p">=</span>
    <span class="k">match</span> <span class="n">tree</span> <span class="k">with</span>
    <span class="p">|</span> <span class="nc">Leaf</span> <span class="p">-&gt;</span> <span class="mi">1</span>
    <span class="p">|</span> <span class="nc">Node</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="n">numberOfLeaves</span> <span class="n">l</span> <span class="o">+</span> <span class="n">numberOfLeaves</span> <span class="n">r</span>

<span class="p">[&lt;</span><span class="nc">Fact</span><span class="p">&gt;]</span>
<span class="k">let</span> <span class="n">``counts the number of leaves in a tree``</span> <span class="bp">()</span> <span class="p">=</span>
    <span class="k">let</span> <span class="n">treeWith3Leaves</span> <span class="p">=</span> <span class="nc">Node</span><span class="p">(</span><span class="nc">Leaf</span><span class="p">,</span> <span class="nc">Node</span><span class="p">(</span><span class="nc">Leaf</span><span class="p">,</span> <span class="nc">Leaf</span><span class="o">))</span>

    <span class="k">let</span> <span class="n">leaves</span> <span class="p">=</span> <span class="n">numberOfLeaves</span> <span class="n">treeWith3Leaves</span>

    <span class="n">test</span> <span class="o">&lt;@</span> <span class="n">leaves</span> <span class="p">=</span> <span class="mi">3</span> <span class="o">@&gt;</span>
</code></pre></div></div>

<p>You can see how the:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="p">|</span> <span class="nc">Leaf</span> <span class="p">-&gt;</span> <span class="mi">1</span>
</code></pre></div></div>

<p>branch is the <em>base case</em> of recursion, while the:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code>    <span class="p">|</span> <span class="nc">Node</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="n">numberOfLeaves</span> <span class="n">l</span> <span class="o">+</span> <span class="n">numberOfLeaves</span> <span class="n">r</span>
</code></pre></div></div>

<p>is the (double) recursive step.<br />
Also notice how the results of the 2 recursive calls are <em>composed</em>
with the binary <code class="language-plaintext highlighter-rouge">+</code> function.</p>

<h2 id="f-3-concisiness-and-haskell-loves-it-too">F# &lt;3 concisiness (and Haskell loves it too)</h2>
<p>In:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="k">rec</span> <span class="n">numberOfLeaves</span> <span class="n">tree</span> <span class="p">=</span>
    <span class="k">match</span> <span class="n">tree</span> <span class="k">with</span>
    <span class="p">|</span> <span class="nc">Leaf</span> <span class="p">-&gt;</span> <span class="mi">1</span>
    <span class="p">|</span> <span class="nc">Node</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="n">numberOfLeaves</span> <span class="n">l</span> <span class="o">+</span> <span class="n">numberOfLeaves</span> <span class="n">r</span>
</code></pre></div></div>

<p>the parameter <code class="language-plaintext highlighter-rouge">tree</code> is only used to pattern match. To stress this, F#
provides an alternative, more concise syntax, where</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">...</span> <span class="n">tree</span> <span class="p">=</span>
    <span class="k">match</span> <span class="n">tree</span> <span class="k">with</span>
</code></pre></div></div>

<p>is replaced by:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">...</span> <span class="k">function</span> <span class="p">=</span>
</code></pre></div></div>

<p>So, our function can be made shorter, as:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">let</span> <span class="k">rec</span> <span class="n">numberOfLeaves</span> <span class="p">=</span> 
    <span class="k">function</span>
    <span class="p">|</span> <span class="nc">Leaf</span> <span class="p">-&gt;</span> <span class="mi">1</span>
    <span class="p">|</span> <span class="nc">Node</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="p">-&gt;</span> <span class="n">numberOfLeaves</span> <span class="n">l</span> <span class="o">+</span> <span class="n">numberOfLeaves</span> <span class="n">r</span>
</code></pre></div></div>

<p>A nice way to interpret this is to squeeze the eyes and imagine it’s a
combination of 2 separate function definitions, one on <code class="language-plaintext highlighter-rouge">Leaf</code> and one
on <code class="language-plaintext highlighter-rouge">Node(l, r)</code>. Haskell would really let you define 2 separate functions:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">numberOfLeaves</span> <span class="kt">Leaf</span>       <span class="o">=</span> <span class="mi">1</span>
<span class="n">numberOfLeaves</span> <span class="kt">Node</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="o">=</span> <span class="n">numberOfLeaves</span> <span class="n">l</span> <span class="o">+</span> <span class="n">numberOfLeaves</span> <span class="n">r</span>
</code></pre></div></div>

<p>If you manage to understand this last snippet, <em>bravo</em>!, give yourself
a pat on the back, take a little breather, and get prepared to the
next chapter, in which you will invent (<a href="https://www.youtube.com/watch?v=IOiZatlZtGU">or
discover</a>) Functors.</p>

<p>Jump to <a href="state-monad-for-the-rest-of-us-2">Chapter 2</a>.</p>

<h1 id="references">References</h1>

<ul>
  <li><a href="https://github.com/arialdomartini/state-monad-for-the-rest-of-us">State Monad For The Rest Of Us - source code</a></li>
  <li><a href="https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/pattern-matching#identifier-patterns">Microsoft Learn - Pattern Matching - Identifier Patterns</a></li>
  <li><a href="https://www.youtube.com/watch?v=IOiZatlZtGU">Philip Wadler - Propositions as Types</a></li>
</ul>

<h1 id="comments">Comments</h1>
<p><a href="https://github.com/arialdomartini/arialdomartini.github.io/discussions/30">GitHub Discussions</a></p>

<h2>Functional Programming For The Rest Os Us</h2>

<p>Interested in FP? Be the first to be notified when new introductory
articles on the topic are published.<br /></p>

<iframe class="newsletter-subscription" src="https://embeds.beehiiv.com/55b1bb2e-e731-466f-8d1e-82b51d67a9ef?slim=true" data-test-id="beehiiv-embed" height="52" frameborder="0" scrolling="no" style="margin: 0; margin-top:5px; border-radius: 0px !important; background-color: transparent;"></iframe>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="F#" /><category term="Functional Programming" /><summary type="html"><![CDATA[Index Source code: github.com/arialdomartini/state-monad-for-the-rest-of-us Binary Trees Our journey starts with this problem: we want to count the number of leaves of an arbitrary Binary Tree. To keep the problem as simple as possible, we define a Binary Tree as that data structure having Nodes and Leaves, and in which every Node has exactly two branches. This is a Tree with 2 Leaves: Node / \ Leaf Leaf and here is a Tree with 3 Leaves: Node / \ Leaf Node / \ Leaf Leaf It is legit to ask ourselves: is a single Leaf a Tree? Leaf Let’s agree that it is. Do null Trees — Trees without Nodes and Leaves — exist? Let’s do ourselves a favor and agree they don’t. A Node always contains 2 Leaves. What does a Leaf contain? Nothing: it just is. So, a Tree is either a Leaf or a Node made of 2 branches, each containing another Tree structure. Remember this definition, because we will translate it more or less literally to F#. How deep can such Binary Trees be? Arbitrarily deep. For example, this is a legit Tree: Node / \ Leaf Node / \ Node Leaf / \ Leaf Node / \ Node Leaf / \ Leaf Node / \ Leaf Leaf Of course, our code should work with any Tree, no matter how deep. Counting Leaves Good. We are diligent developers, so we start from a test. To keep it simple, let’s count the Leaves of a 3-leaves Tree: module StateMonadTest open Xunit open Swensen.Unquote let numberOfLeaves tree = failwith "Not yet implemented" [&lt;Fact&gt;] let ``counts the number of leaves in a tree`` () = let treeWith3Leaves = failwith "Not yet implemented" let leaves = numberOfLeaves treeWith3Leaves test &lt;@ leaves = 3 @&gt; Let’s fill the gaps. As often happens with Functional Programming, it is convenient to start from modeling problems through their types. Sum and Product Types How to model a Tree? That’s an easy task in F#: it’s a matter of translating literally our definition: A Tree is either a Leaf or a Node containing 2 branches each containing another Tree structure. Step by step: A Tree is is simply translated to type Tree = A Tree can be a Leaf: type Tree = Leaf or a Node. The or part is translated with the | operator: type Tree = Leaf | Node ??? The Node contains 2 branches. The contain part is translated with of, the multiplicity is translated with *: type Tree = Leaf | Node of (??? * ???) We know that each branch contains either a Leaf or another Node. We already have a type representing either a Leaf or a Node, dont’t we? It’s the Tree itself. So: type Tree = Leaf | Node of (Tree * Tree) That’s it! As an aside, this expression makes use of the so called Algebraic Data Types, which include Sum (or Discriminated Union) Types and Product Types. Name Symbol used Equivalent technique in OOP Sum Types | Inheritance Product Types * Multiple fieds in classes In C# this would approximately translate to: abstract record Tree; record Leaf : Tree; record Node(Tree Left, Tree Right) : Tree; In both cases, we have a recursive type, which both languages happily support. Creating instances Creating instances in F# is similar, but more concise, than in C# and Java: you just have to omit the new keyword and the parenthesis. Our 3-leaves tree: Node / \ Leaf Node / \ Leaf Leaf can be created with: let treeWith3Leaves = Node(Leaf, Node(Leaf, Leaf)) This completes the test implementation: [&lt;Fact&gt;] let ``counts the number of leaves in a tree`` () = let treeWith3Leaves = Node(Leaf, Node(Leaf, Leaf)) let leaves = numberOfLeaves treeWith3Leaves test &lt;@ leaves = 3 @&gt; Good. Now, let’s see how to make it green. Type Constructors and Data Constructors It is important to understand that in: type Tree = Leaf | Node of (Tree * Tree) Tree is a type, Leaf and Node are not: Leaf and Node are ways for creating an instance of type Tree. This is akin to the difference between a class and its constructors. In F#, we would call Tree, Leaf and Nodeas follows: Element Name Tree Discriminated Union Type Leaf and Node of (Tree * Tree) Union Case Haskell uses different names, but the meaning is the same: Element Name Tree Type Constructor Leaf and Node Tree Tree Data Constructor We will shortly see why Tree is a Type Constructor, not just a Type: as soon as Tree will take a (type) parameter, we will learn to see it more as a function than just a type name. The takeaway here is: given an instance of Tree, F# can pattern match on the Case which was used to create the instance. It’s like the instance remembers which constructor was used to create it. You can read more about it in Pattern Matching - Identifier Patterns. This give you all the ingredients to develop a function to calculate the number of leaves. Implementation Pattern matching is easy: let numberOfLeaves tree = match tree with | Leaf -&gt; ??? | Node (l, r) -&gt; ??? Read it as a glorified if/then/else and ask yourself: If numberOfLeaves receives a tree, and that tree is a single Leaf, how many leaves does that tree have? In other words, the function needs to calculate the number of leaves of this tree: Leaf Of course, it has just 1 leaf! So: let numberOfLeaves tree = match tree with | Leaf -&gt; 1 | Node (l, r) -&gt; ??? What about if tree is a Node? You only know that a Node contains exactly 2 branches. Each branch could be a Leaf, like in: Node / \ Leaf Leaf or it could be another arbitrarily deep tree, like in: Node / \ Leaf Node / \ Node Leaf / \ Leaf Node / \ Node Leaf / \ Leaf Node / \ Leaf Leaf In the general case, you can see the received tree as: Node / \ Tree Tree This node contains as many leaves as the leaves in the right branch tree, plus the leaves of the left branch tree. Literally translating this sentence to F# leads us to: let rec numberOfLeaves tree = match tree with | Leaf -&gt; 1 | Node (l, r) -&gt; numberOfLeaves l + numberOfLeaves r Notice that we added the keyword rec to the function definition, to make it clear that the function is recursive. Does this work? You have a test. Run it. Of course it’s green. As it often happens, if it compiles it works. Get used to this, it will happen over and over. Putting all together Let’s review what you obtained: type Tree = | Leaf | Node of Tree * Tree let rec numberOfLeaves tree = match tree with | Leaf -&gt; 1 | Node(l, r) -&gt; numberOfLeaves l + numberOfLeaves r [&lt;Fact&gt;] let ``counts the number of leaves in a tree`` () = let treeWith3Leaves = Node(Leaf, Node(Leaf, Leaf)) let leaves = numberOfLeaves treeWith3Leaves test &lt;@ leaves = 3 @&gt; You can see how the: | Leaf -&gt; 1 branch is the base case of recursion, while the: | Node(l, r) -&gt; numberOfLeaves l + numberOfLeaves r is the (double) recursive step. Also notice how the results of the 2 recursive calls are composed with the binary + function. F# &lt;3 concisiness (and Haskell loves it too) In: let rec numberOfLeaves tree = match tree with | Leaf -&gt; 1 | Node(l, r) -&gt; numberOfLeaves l + numberOfLeaves r the parameter tree is only used to pattern match. To stress this, F# provides an alternative, more concise syntax, where ... tree = match tree with is replaced by: ... function = So, our function can be made shorter, as: let rec numberOfLeaves = function | Leaf -&gt; 1 | Node(l, r) -&gt; numberOfLeaves l + numberOfLeaves r A nice way to interpret this is to squeeze the eyes and imagine it’s a combination of 2 separate function definitions, one on Leaf and one on Node(l, r). Haskell would really let you define 2 separate functions: numberOfLeaves Leaf = 1 numberOfLeaves Node(l, r) = numberOfLeaves l + numberOfLeaves r If you manage to understand this last snippet, bravo!, give yourself a pat on the back, take a little breather, and get prepared to the next chapter, in which you will invent (or discover) Functors. Jump to Chapter 2. References State Monad For The Rest Of Us - source code Microsoft Learn - Pattern Matching - Identifier Patterns Philip Wadler - Propositions as Types Comments GitHub Discussions Functional Programming For The Rest Os Us Interested in FP? Be the first to be notified when new introductory articles on the topic are published.]]></summary></entry><entry><title type="html">State Monad For The Rest Of Us - Part 10</title><link href="http://arialdomartini.github.io/state-monad-for-the-rest-of-us-10" rel="alternate" type="text/html" title="State Monad For The Rest Of Us - Part 10" /><published>2024-07-01T00:00:00+00:00</published><updated>2024-07-01T00:00:00+00:00</updated><id>http://arialdomartini.github.io/state-monad-for-the-rest-of-us-10</id><content type="html" xml:base="http://arialdomartini.github.io/state-monad-for-the-rest-of-us-10"><![CDATA[<p><a href="state-monad-for-the-rest-of-us">Index</a><br />
Source code:
<a href="https://github.com/arialdomartini/state-monad-for-the-rest-of-us">github.com/arialdomartini/state-monad-for-the-rest-of-us</a></p>

<p>In <a href="state-monad-for-the-rest-of-us-7">chapter 7</a>, when we wanted to
introduce a new type for the result value of <code class="language-plaintext highlighter-rouge">index</code> we got to this:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// Tree a -&gt; (Int -&gt; (Tree (a, Int), Int))</span>
<span class="k">let</span> <span class="k">rec</span> <span class="n">index</span> <span class="p">=</span>
    <span class="k">function</span>
    <span class="p">|</span> <span class="nc">Leaf</span> <span class="n">v</span> <span class="p">-&gt;</span> <span class="k">fun</span> <span class="n">count</span> <span class="p">-&gt;</span> <span class="p">(</span><span class="nc">Leaf</span> <span class="p">(</span><span class="n">v</span><span class="p">,</span> <span class="n">count</span><span class="o">),</span> <span class="n">count</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
    <span class="p">|</span> <span class="nc">Node</span> <span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">r</span><span class="p">)</span> <span class="p">-&gt;</span>
        <span class="k">fun</span> <span class="n">count</span> <span class="p">-&gt;</span>
            <span class="k">let</span> <span class="n">li</span><span class="p">,</span> <span class="n">lc</span> <span class="p">=</span> <span class="n">index</span> <span class="n">l</span> <span class="n">count</span>
            <span class="k">let</span> <span class="n">ri</span><span class="p">,</span> <span class="n">rc</span> <span class="p">=</span> <span class="n">index</span> <span class="n">r</span> <span class="n">lc</span>
            <span class="nc">Node</span> <span class="p">(</span><span class="n">li</span><span class="p">,</span> <span class="n">ri</span><span class="o">),</span> <span class="n">rc</span>
</code></pre></div></div>

<p>I mentioned that there was a second perspective, leading to the same
signature of <code class="language-plaintext highlighter-rouge">WithCount</code>:</p>

<ul>
  <li>Manipulate the signature, separating the <code class="language-plaintext highlighter-rouge">count</code>-handling and domain
logic on the type level.</li>
</ul>

<p>Let us do this, because it will lead to some interesting refinements</p>

<h2 id="working-on-the-signature">Working on the signature</h2>
<p>Observing again the original signature:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">Tree</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="kt">Int</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="kt">Tree</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="kt">Int</span><span class="p">),</span> <span class="kt">Int</span><span class="p">))</span>
</code></pre></div></div>

<p>it’s not hard to see what happened. Ideally, you wanted a simple function:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">Tree</span> <span class="n">a</span> <span class="o">-&gt;</span> <span class="kt">Tree</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="kt">Int</span><span class="p">)</span>
</code></pre></div></div>

<p>taking a tree of whatever content and returning an indexed version of
it. This is the original domain logic, which you can easily make more
generic with:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="kt">Int</span><span class="p">)</span>
</code></pre></div></div>

<p>Then, you wanted to have a Functor to take care of the logic for
traversing a tree. But then you found out that Functors are not
powerful enough to apply an indexing function with <code class="language-plaintext highlighter-rouge">map</code>.</p>

<p>Instead of that, you ended up with:</p>

<table>
  <thead>
    <tr>
      <th>Pure logic</th>
      <th>What you got</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">Tree a -&gt; Tree (a, Int)</code></td>
      <td><code class="language-plaintext highlighter-rouge">Tree a -&gt; (Int -&gt; (Tree (a, Int), Int))</code></td>
    </tr>
  </tbody>
</table>

<p>or, generalizing:</p>

<table>
  <thead>
    <tr>
      <th>Pure logic</th>
      <th>What you got</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code class="language-plaintext highlighter-rouge">a -&gt; b</code></td>
      <td><code class="language-plaintext highlighter-rouge">a -&gt; (Int -&gt; (b, Int))</code></td>
    </tr>
  </tbody>
</table>

<p>Squint the eyes. This expression contains the domain logic and the
count-handling logic mixed together. Let me move the count-handling
logic to a separate line:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">Tree</span> <span class="n">a</span> <span class="o">-&gt;</span>           <span class="kt">Tree</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="kt">Int</span><span class="p">)</span>
          <span class="p">(</span><span class="kt">Int</span> <span class="o">-&gt;</span> <span class="p">(</span>               <span class="p">,</span> <span class="kt">Int</span><span class="p">))</span>
</code></pre></div></div>

<p>or if you want to make to use the more generic version:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span> <span class="o">-&gt;</span>            <span class="n">b</span>
     <span class="p">(</span><span class="kt">Int</span> <span class="o">-&gt;</span> <span class="p">(</span>    <span class="p">,</span> <span class="kt">Int</span><span class="p">))</span>
</code></pre></div></div>

<p>The:</p>

<div class="language-haskell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">Int</span> <span class="o">-&gt;</span> <span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="kt">Int</span><span class="p">)</span>
</code></pre></div></div>

<p>captures exactly what you did in <a href="state-monad-for-the-rest-of-us-6">chapter
6</a>:</p>

<table>
  <thead>
    <tr>
      <th>What you did</th>
      <th> </th>
      <th> </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>You return a function getting the previous <code class="language-plaintext highlighter-rouge">count</code> value</td>
      <td><code class="language-plaintext highlighter-rouge">Int</code></td>
      <td> </td>
    </tr>
    <tr>
      <td>You return the domain logic result <em>plus</em> the next <code class="language-plaintext highlighter-rouge">count</code> value</td>
      <td> </td>
      <td><code class="language-plaintext highlighter-rouge">-&gt; (b, Int)</code></td>
    </tr>
  </tbody>
</table>

<p>If you want to give this idea a name and to capture it with a type, it
makes sense to define it with:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">WithCount</span><span class="p">&lt;</span><span class="k">'</span><span class="n">b</span><span class="p">&gt;</span> <span class="p">=</span> <span class="nc">WithCount</span> <span class="k">of</span> <span class="p">(</span><span class="kt">int</span> <span class="p">-&gt;</span> <span class="k">'</span><span class="n">b</span> <span class="p">*</span> <span class="kt">int</span><span class="p">)</span>
</code></pre></div></div>

<p>Of course, this could be more specific to trees:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">WithCount</span><span class="p">&lt;</span><span class="k">'</span><span class="n">b</span><span class="p">&gt;</span> <span class="p">=</span> <span class="nc">WithCount</span> <span class="k">of</span> <span class="p">(</span><span class="kt">int</span> <span class="p">-&gt;</span> <span class="nc">Tree</span><span class="p">&lt;</span><span class="k">'</span><span class="n">b</span><span class="p">&gt;</span> <span class="p">*</span> <span class="kt">int</span><span class="p">)</span>
</code></pre></div></div>

<p>or even more specif to our indexing use-case:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">WithCount</span> <span class="p">=</span> <span class="nc">WithCount</span> <span class="k">of</span> <span class="p">(</span><span class="kt">int</span> <span class="p">-&gt;</span> <span class="nc">Tree</span><span class="p">&lt;</span><span class="kt">string</span><span class="p">,</span> <span class="kt">int</span><span class="p">&gt;</span> <span class="p">*</span> <span class="kt">int</span><span class="p">)</span>
</code></pre></div></div>

<p>but why should it be? On the contrary, it could be generic also on the
type of the counter:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">WithCount</span><span class="p">&lt;</span><span class="k">'</span><span class="n">b</span><span class="p">,</span> <span class="k">'</span><span class="n">c</span><span class="p">&gt;</span> <span class="p">=</span> <span class="nc">WithCount</span> <span class="k">of</span> <span class="p">(</span><span class="k">'</span><span class="n">c</span> <span class="p">-&gt;</span> <span class="k">'</span><span class="n">b</span> <span class="p">*</span> <span class="k">'</span><span class="n">c</span><span class="p">)</span>
</code></pre></div></div>

<p>where <code class="language-plaintext highlighter-rouge">'c</code> is the type of the state being chained, and <code class="language-plaintext highlighter-rouge">'b</code> is the
original domain logic result type.<br />
<code class="language-plaintext highlighter-rouge">c</code> is not a count anymore, it’s a generic state. Let’s call it <code class="language-plaintext highlighter-rouge">s</code>.
And <code class="language-plaintext highlighter-rouge">WithCount</code> is a misleading name. We can easily call it <code class="language-plaintext highlighter-rouge">State</code>:</p>

<div class="language-fsharp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">type</span> <span class="nc">State</span><span class="p">&lt;</span><span class="k">'</span><span class="n">b</span><span class="p">,</span> <span class="k">'</span><span class="n">s</span><span class="p">&gt;</span> <span class="p">=</span> <span class="nc">State</span> <span class="k">of</span> <span class="p">(</span><span class="k">'</span><span class="n">s</span> <span class="p">-&gt;</span> <span class="p">(</span><span class="k">'</span><span class="n">b</span> <span class="p">*</span> <span class="k">'</span><span class="n">s</span><span class="o">))</span>
</code></pre></div></div>

<p>This generalized version of <code class="language-plaintext highlighter-rouge">WithCount</code> is, ladies and gentlemen, the
signature of the State Monad.<br />
It’s definitely the time to implement it. Ready! Steady! Go with
<a href="state-monad-for-the-rest-of-us-11">Chapter 11</a>!</p>

<h1 id="references">References</h1>
<ul>
  <li><a href="https://github.com/arialdomartini/state-monad-for-the-rest-of-us">State Monad For The Rest Of Us - source code</a></li>
</ul>

<h1 id="comments">Comments</h1>
<p><a href="https://github.com/arialdomartini/arialdomartini.github.io/discussions/30">GitHub Discussions</a></p>]]></content><author><name>&lt;a href=&quot;https://arialdomartini.github.io&quot;&gt;Arialdo Martini&lt;/a&gt;</name></author><category term="F#" /><category term="Functional Programming" /><summary type="html"><![CDATA[Index Source code: github.com/arialdomartini/state-monad-for-the-rest-of-us In chapter 7, when we wanted to introduce a new type for the result value of index we got to this: // Tree a -&gt; (Int -&gt; (Tree (a, Int), Int)) let rec index = function | Leaf v -&gt; fun count -&gt; (Leaf (v, count), count + 1) | Node (l, r) -&gt; fun count -&gt; let li, lc = index l count let ri, rc = index r lc Node (li, ri), rc I mentioned that there was a second perspective, leading to the same signature of WithCount: Manipulate the signature, separating the count-handling and domain logic on the type level. Let us do this, because it will lead to some interesting refinements Working on the signature Observing again the original signature: Tree a -&gt; (Int -&gt; (Tree (a, Int), Int)) it’s not hard to see what happened. Ideally, you wanted a simple function: Tree a -&gt; Tree (a, Int) taking a tree of whatever content and returning an indexed version of it. This is the original domain logic, which you can easily make more generic with: a -&gt; (a, Int) Then, you wanted to have a Functor to take care of the logic for traversing a tree. But then you found out that Functors are not powerful enough to apply an indexing function with map. Instead of that, you ended up with: Pure logic What you got Tree a -&gt; Tree (a, Int) Tree a -&gt; (Int -&gt; (Tree (a, Int), Int)) or, generalizing: Pure logic What you got a -&gt; b a -&gt; (Int -&gt; (b, Int)) Squint the eyes. This expression contains the domain logic and the count-handling logic mixed together. Let me move the count-handling logic to a separate line: Tree a -&gt; Tree (a, Int) (Int -&gt; ( , Int)) or if you want to make to use the more generic version: a -&gt; b (Int -&gt; ( , Int)) The: Int -&gt; (b, Int) captures exactly what you did in chapter 6: What you did     You return a function getting the previous count value Int   You return the domain logic result plus the next count value   -&gt; (b, Int) If you want to give this idea a name and to capture it with a type, it makes sense to define it with: type WithCount&lt;'b&gt; = WithCount of (int -&gt; 'b * int) Of course, this could be more specific to trees: type WithCount&lt;'b&gt; = WithCount of (int -&gt; Tree&lt;'b&gt; * int) or even more specif to our indexing use-case: type WithCount = WithCount of (int -&gt; Tree&lt;string, int&gt; * int) but why should it be? On the contrary, it could be generic also on the type of the counter: type WithCount&lt;'b, 'c&gt; = WithCount of ('c -&gt; 'b * 'c) where 'c is the type of the state being chained, and 'b is the original domain logic result type. c is not a count anymore, it’s a generic state. Let’s call it s. And WithCount is a misleading name. We can easily call it State: type State&lt;'b, 's&gt; = State of ('s -&gt; ('b * 's)) This generalized version of WithCount is, ladies and gentlemen, the signature of the State Monad. It’s definitely the time to implement it. Ready! Steady! Go with Chapter 11! References State Monad For The Rest Of Us - source code Comments GitHub Discussions]]></summary></entry></feed>