<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" >

  <title>Erik L. Arneson — Writer and Software Developer</title>
  <subtitle>Erik L. Arneson is a freelance writer and software developer with WordPress experience. He is located in Portland, Oregon.</subtitle>
  <generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator>
  <link href="https://arnesonium.com/feeds/emacs-lisp.xml" rel="self" type="application/atom+xml" />
  <link href="https://arnesonium.com/" rel="alternate" type="text/html" />
  <updated>2026-06-18T15:03:10+00:00</updated>
  <id>https://arnesonium.com/feeds/emacs-lisp.xml</id>
  <author>
    <name>Erik L. Arneson</name>
  </author>
      <entry>
        
        <title>Emacs as the Freelancer&apos;s Command Center</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2026/04/emacs-freelance-command-center" rel="alternate" type="text/html" title="Emacs as the Freelancer's Command Center" />
        <updated>2026-04-10T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2026/04/emacs-freelance-command-center</id>
          <category term="emacs" />
        
          <category term="org-mode" />
        
          <category term="programming" />
        
          <category term="writing" />
        
          <category term="music" />
        
          <category term="wordpress" />
        
          <category term="emacs-lisp" />
        
          <category term="email" />
        
          <category term="git" />
        
          <category term="tools" />
        <content type="html" xml:base="https://arnesonium.com/2026/04/emacs-freelance-command-center">&lt;p&gt;Freelancing for small businesses and organizations leads to a position where you are juggling a
number of projects for multiple clients. You need to keep track of a number of tasks ranging from
software development to sending emails to project management. This is a lot easier when you have a
system that can do a bunch of the work for you, which is why I use Emacs as my freelancer command
center.&lt;/p&gt;

&lt;p&gt;I would like to share some of the tools and workflows I use in Emacs to help me keep on top of
multiple clients’ needs and expectations.&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;organization-with-org-mode&quot;&gt;Organization with org-mode&lt;/h2&gt;

&lt;p&gt;It should be no surprise that at the center of my Emacs command center is &lt;a href=&quot;https://orgmode.org/&quot;&gt;org-mode&lt;/a&gt;. I have already
&lt;a href=&quot;/tags/org-mode/&quot;&gt;written about it a lot&lt;/a&gt;. Every org-mode user seems to have their own way of keeping track of things,
so please don’t take my organizational scheme as some kind of gospel. A couple of years ago, I wrote
about &lt;a href=&quot;/2024/10/todo-lists-in-org-mode&quot;&gt;how I handle to-do lists in org-mode&lt;/a&gt;, and I am still using that method for to-do keywords.
However, file structure is also important. I have a number of core files.&lt;/p&gt;

&lt;h3 id=&quot;freelanceorg&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Freelance.org&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;This top-level file contains all of my ongoing business tasks, such as tracking potential new
clients, recurring tasks like website maintenance and checking my &lt;a href=&quot;https://mainwp.com/&quot;&gt;MainWP dashboard&lt;/a&gt;. I also have
recurring tasks for invoicing, tracking expenses, and other important business things.&lt;/p&gt;

&lt;p&gt;This file is also where I have my primary time tracking and reporting. Org-mode already supports
this pretty nicely, I just use the built-in &lt;a href=&quot;https://orgmode.org/manual/The-clock-table.html&quot;&gt;clocktable feature&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;clientsorg&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Clients/*.org&lt;/code&gt;&lt;/h3&gt;

&lt;p&gt;Clients that have large projects or ongoing business get their own file. This makes organization a
lot easier. All tasks associated with a client and their various projects end up in these individual
files. The important part is making sure that these files are included in the time-tracking
clock table &lt;em&gt;and&lt;/em&gt; your org-mode agenda, so you can see what is going on every week.&lt;/p&gt;

&lt;h3 id=&quot;references-and-linking&quot;&gt;References and Linking&lt;/h3&gt;

&lt;p&gt;I have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C-c l&lt;/code&gt; bound to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org-store-link&lt;/code&gt; and use it all the time to link to various files,
directories, URLs, and even emails. I can then use those links in my client notes, various tasks in
my to-do list, and so on. This helps me keep my agenda organized even when my filesystem and
browser bookmarks are a bit of a mess.&lt;/p&gt;

&lt;h2 id=&quot;email-with-mu4e&quot;&gt;Email with mu4e&lt;/h2&gt;

&lt;p&gt;I have been reading and managing my email in Emacs for over 25 years. There have been a few breaks
here and there where I have tried out other software or even web mail clients, but it has always been
a headache. I return to Emacs! Long ago, I used &lt;a href=&quot;https://gitlab.com/emacs-vm/vm&quot;&gt;VM&lt;/a&gt; (which seems to have taken on new life!), but
currently I use &lt;a href=&quot;https://djcbsoftware.nl/code/mu/mu4e/index.html&quot;&gt;mu4e&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This gives me a ton of power and flexibility when dealing with email. I have custom functions to
help me compose and organize my email, and I can use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;org-store-link&lt;/code&gt; to keep track of individual
emails from clients as they relate to agenda items. I even have a function to convert emails that I
have written in Markdown into HTML email, and one that searches for questions in a client email to
make sure I haven’t missed anything.&lt;/p&gt;

&lt;p&gt;The ability to write custom code to both process and create email is extremely powerful and a great
time saver.&lt;/p&gt;

&lt;h2 id=&quot;writing-code&quot;&gt;Writing Code&lt;/h2&gt;

&lt;p&gt;I don’t know what else to say about this, I use Emacs for doing all of my software development. I
make sure to use &lt;a href=&quot;https://github.com/joaotavora/eglot&quot;&gt;Eglot&lt;/a&gt; whenever there is a language server available, and I try to leverage all the
fancy features offered by Emacs whenever possible. The vast majority of projects for clients are PHP
(thanks &lt;a href=&quot;/wordpress/&quot;&gt;WordPress&lt;/a&gt;), Go, JavaScript, and TypeScript.&lt;/p&gt;

&lt;h2 id=&quot;writing-words&quot;&gt;Writing Words&lt;/h2&gt;

&lt;p&gt;Previously, I have shared quite a bit about &lt;a href=&quot;/tags/writing/&quot;&gt;writing in Emacs&lt;/a&gt;. I like to start everything in
org-mode, but I also write quite a bit in Markdown. Emacs has become a powerful tool for writing. I
use the &lt;a href=&quot;https://writewithharper.com/&quot;&gt;Harper language server&lt;/a&gt; along with Eglot to check grammar and spelling.&lt;/p&gt;

&lt;h2 id=&quot;track-all-changes-with-magit&quot;&gt;Track All Changes with Magit&lt;/h2&gt;

&lt;p&gt;Version control is essential, a lesson I have learned over 30+ years of software development. While
&lt;a href=&quot;https://git-scm.com/&quot;&gt;Git&lt;/a&gt; is not part of Emacs, the software I use to interface with Git is. &lt;a href=&quot;https://magit.vc/&quot;&gt;Magit&lt;/a&gt; is a Git user interface
that runs entirely in Emacs. I use it to track my writing, my source code, and even all of my
org-mode files. Using version control is so essential that I have a weekly repeating agenda task
reminding me to check all of my everyday files to make sure I have checked-in my changes for the
week.&lt;/p&gt;

&lt;h2 id=&quot;thinking-music-with-emms&quot;&gt;Thinking Music with EMMS&lt;/h2&gt;

&lt;p&gt;I like to have some soothing background music when I am programming, writing, or otherwise working
on my computer. However, if that background music has lyrics, it can be really distracting. It is
easy to make a playlist for various suitable &lt;a href=&quot;https://somafm.com/&quot;&gt;SomaFM&lt;/a&gt; channels to load into &lt;a href=&quot;https://www.gnu.org/software/emms/&quot;&gt;EMMS (the Emacs Multimedia
System)&lt;/a&gt; using the command &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x emms-play-playlist&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Try saving the following into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;playlist.el&lt;/code&gt; somewhere, and using it the next time you are writing:&lt;/p&gt;

&lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt; &lt;span class=&quot;c1&quot;&gt;;;; This is an EMMS playlist file Play it with M-x emms-play-playlist&lt;/span&gt;
 &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;*track*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://somafm.com/synphaera.pls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;*track*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://somafm.com/gsclassic.pls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;*track*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://somafm.com/sonicuniverse.pls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vg&quot;&gt;*track*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://somafm.com/groovesalad.pls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And make sure to check out SomaFM’s selection to find some good background music that suits your
tastes!&lt;/p&gt;

&lt;h2 id=&quot;and-the-tools-i-have-missed&quot;&gt;And the tools I have missed&lt;/h2&gt;

&lt;p&gt;There are undoubtedly Emacs tools that I have missed in this brief overview. I have been wracking my
brain as I write, trying to see what I have forgotten or overlooked. Frankly, Emacs has become such
a central part of the organization for my freelancing that there are probably many tools, packages,
and processes that I use every day without thinking about it too much.&lt;/p&gt;

&lt;p&gt;Emacs makes it possible for me to freelance for multiple clients and small businesses without losing
my mind with organization and task management. The tools it provides allow me to stay on top of
multiple projects, handle client relationships, and keep track of years worth of tasks,
communications, and projects. Without it, I’d be sunk!&lt;/p&gt;

&lt;p&gt;What Emacs tools are you using to manage your freelance business? I am always looking for ways to
improve or streamline my process.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The featured image for this post comes from Agostino Ramelli’s&lt;/em&gt; Le diverse et artificiose machine &lt;em&gt;(1588). &lt;a href=&quot;https://publicdomainreview.org/collection/agostino-ramelli-theatre-of-machines/&quot;&gt;Read more about it on the Public Domain Review.&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;</content>
      </entry>
    
      <entry>
        
        <title>Posts of Interest for 13 October 2023</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2023/10/13-posts-of-interest" rel="alternate" type="text/html" title="Posts of Interest for 13 October 2023" />
        <updated>2023-10-13T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2023/10/of-interest</id>
          <category term="emacs" />
        
          <category term="programming" />
        
          <category term="emacs-lisp" />
        
          <category term="security" />
        <content type="html" xml:base="https://arnesonium.com/2023/10/13-posts-of-interest">&lt;p&gt;This is the second of my “posts of interest” posts. This week, I have also included some interesting Mastodon posts, because the Emacs community on Mastodon is thriving like crazy. It is really a blast to see so much interest in Emacs and so much activity.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;If Mastodon interests you, &lt;a href=&quot;https://fosstodon.org/@pymander&quot;&gt;find me there&lt;/a&gt;!&lt;/p&gt;

&lt;h2 id=&quot;programming-1&quot;&gt;Programming (1)&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://spritely.institute/news/scheme-wireworld-in-browser.html&quot;&gt;Scheme in the browser: A Hoot of a tale&lt;/a&gt; – Spritely Institute
Yes, SCHEME IN THE BROWSER. This is pretty cool, go check it out.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;emacs-6&quot;&gt;Emacs (6)&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://coredumped.dev/2023/08/09/text-showdown-gap-buffers-vs-ropes/&quot;&gt;Text showdown: Gap Buffers vs Ropes&lt;/a&gt; &lt;strong&gt;[Programming, Rust]&lt;/strong&gt;
Troy Hinckley has been working on building the core of Emacs in Rust. This sounds like a very
difficult project, and it is informative and interesting to follow along. The latest entry in his
saga involves various ways of storing and working with text buffers, along with many benchmarks.
This is an interesting read!&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://amodernist.com/eaez/./sep23.html&quot;&gt;ELPA and Emacs Zine (September 2023)&lt;/a&gt;
The new ELPA and Emacs Zine has released its latest issue, with some pretty interesting stuff about
the current state of tree-sitter and how development is progressing.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://functional.cafe/@PaniczGodek/111187231582720915&quot;&gt;Emacs Macros&lt;/a&gt; &lt;strong&gt;[Mastodon]&lt;/strong&gt;
Emacs macros remain kind of a mystery to me, but they were presented in an interesting way recently:
these are ways to provide a high level of automation in Emacs without learning how to program Emacs
Lisp. Well, they are worth checking out, then!&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://fosstodon.org/@chmouel/111203691941968313&quot;&gt;Taking advantage of tree-sitter&lt;/a&gt; &lt;strong&gt;[Mastodon]&lt;/strong&gt;
This is a really cool Emacs function that takes advantage of tree-sitter to copy the current
function. I think it might need something to detect if tree-sitter is active, and error out if not.
    &lt;div class=&quot;language-emacs-lisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;my-copy-function-name-with-ts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;interactive&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;funcname&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;substring-no-properties&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;treesit-node-text&lt;/span&gt;
           &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;treesit-node-child-by-field-name&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;treesit-defun-at-point&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;kill-new&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;funcname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Copied name: %s&quot;&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;funcname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://octodon.social/@fabionatali/111210018767997686&quot;&gt;XMPP in Emacs&lt;/a&gt; &lt;strong&gt;[Mastodon]&lt;/strong&gt;
Fabio Natali on Mastodon reports that his XMPP usage would be more consistent if Emacs supported it
better. In particular, he misses E2E encryption support. I’ve also had a lot of difficulty with
moving to XMPP.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://alexschroeder.ch/view/2023-10-11-post-from-emacs&quot;&gt;Alex Schroeder: Posting to Oddµ from Emacs&lt;/a&gt; (Alex Schroeder)
Alex Schroeder provides a simple, straightforward way to use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;url&lt;/code&gt; package in Emacs to post
stuff to another service. In this example, he uses Oddμ.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;security-4&quot;&gt;Security (4)&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://securityintelligence.com/posts/c-suite-weighs-generative-ai-security/&quot;&gt;C-suite weighs in on generative AI and security&lt;/a&gt; (Chris McCurdy)
More on the adoption of generative AI and security risks. 96% of business leaders say adopting generative AI makes a security breach likely in their organization within the next three
years! That’s certainly something to think about.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://securityintelligence.com/articles/cost-of-a-data-breach-10-years-in-review/&quot;&gt;10 years in review: Cost of a Data Breach&lt;/a&gt; (Jonathan Reed)
Data breaches are dang expensive! We all know that. This piece explores some of the most important
factors in preventing and mitigating data breaches. There have been some changes in recent years,
some of which are caused by the rise of importance in AI. That means you should probably read the article.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://newsletter.mollywhite.net/p/the-fraud-was-in-the-code&quot;&gt;The fraud was in the code&lt;/a&gt; (Molly White)
In the SBF court case, they actually used a code review to show fraud.&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://www.schneier.com/blog/archives/2023/10/bounty-to-recover-nists-elliptic-curve-seeds.html&quot;&gt;Bounty to Recover NIST’s Elliptic Curve Seeds&lt;/a&gt; (Bruce Schneier)
Here is a delightful story about the history of NIST elliptic curve cryptography and how things came
to be. Also, a cryptographic puzzle about where they may be going!&lt;/li&gt;
&lt;/ul&gt;</content>
      </entry>
    
      <entry>
        
        <title>Configuring Emacs 29.1 for Go Development</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2023/08/configuring-emacs-29-1-for-golang" rel="alternate" type="text/html" title="Configuring Emacs 29.1 for Go Development" />
        <updated>2023-08-01T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2023/08/golang-emacs</id>
          <category term="emacs" />
        
          <category term="programming" />
        
          <category term="golang" />
        
          <category term="lisp" />
        
          <category term="emacs-lisp" />
        <content type="html" xml:base="https://arnesonium.com/2023/08/configuring-emacs-29-1-for-golang">&lt;p&gt;Now that I have &lt;a href=&quot;https://arnesonium.com/2023/07/emacs-29-1-on-ubuntu-22-04-lts&quot;&gt;installed Emacs 29.1&lt;/a&gt;, I needed to get it set up for Go development for a project. I was interested in taking advantage of both the new Tree-Sitter integration, and the new Eglot language server client. However, they were mildly tricky to set up! Here is what I did.
&lt;!--more--&gt;&lt;/p&gt;

&lt;h2 id=&quot;configuring-tree-sitter-for-go&quot;&gt;Configuring Tree-Sitter for Go&lt;/h2&gt;

&lt;p&gt;If you follow the excellent &lt;a href=&quot;https://www.masteringemacs.org/article/how-to-get-started-tree-sitter&quot;&gt;How to Get Started with Tree-Sitter&lt;/a&gt; instructions from Mickey Peterson, you will have a great head-start on getting Tree-Sitter working for most of your favorite languages (and probably Java, too). However, those instructions didn’t cover everything I needed for Go. When I tried running &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x go-ts-mode&lt;/code&gt;, Emacs complained about a missing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gomod&lt;/code&gt; module. Baffling!&lt;/p&gt;

&lt;p&gt;I couldn’t find any information in the Emacs documentation about where to find this missing module. I looked around on the net and found &lt;a href=&quot;https://github.com/camdencheek/tree-sitter-go-mod&quot;&gt;Camden Cheek’s tree-sitter-go-mod&lt;/a&gt;, and added that to my list of recipes. My &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;treesit-language-source-alist&lt;/code&gt; then looked like this:&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;treesit-language-source-alist&lt;/span&gt;
 &lt;span class=&quot;o&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;bash&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-bash&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cmake&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/uyha/tree-sitter-cmake&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;css&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-css&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;elisp&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/Wilfred/tree-sitter-elisp&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;go&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-go&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;gomod&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/camdencheek/tree-sitter-go-mod&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;dockerfile&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/camdencheek/tree-sitter-dockerfile&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-html&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;javascript&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-javascript&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;master&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;json&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-json&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;make&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/alemuller/tree-sitter-make&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;markdown&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/ikatyang/tree-sitter-markdown&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-python&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;toml&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-toml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tsx&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-typescript&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;master&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;tsx/src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;typescript&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/tree-sitter/tree-sitter-typescript&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;master&quot;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;typescript/src&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
   &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;yaml&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;https://github.com/ikatyang/tree-sitter-yaml&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note that the package is named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go-mod&lt;/code&gt; but &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go-ts-mode&lt;/code&gt; expects it to be named &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gomod&lt;/code&gt;. I wish this were documented somewhere! In any case, I was then able to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x treesit-install-language-grammar&lt;/code&gt; for both &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;go&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gomod&lt;/code&gt;. Finally, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x go-ts-mode&lt;/code&gt; worked!&lt;/p&gt;

&lt;p&gt;After going through this process, I found &lt;a href=&quot;https://robbmann.io/posts/emacs-treesit-auto/&quot;&gt;Robert Enzmann’s post about automatically using Tree-Sitter&lt;/a&gt;. He has created the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;treesit-auto&lt;/code&gt; package, now available on MELPA, that does most of this work for you. It is a much faster way of solving the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gomod&lt;/code&gt; mystery, so give it a shot!&lt;/p&gt;

&lt;h2 id=&quot;configuring-eglot-for-go&quot;&gt;Configuring Eglot for Go&lt;/h2&gt;

&lt;p&gt;I’d been using &lt;a href=&quot;https://github.com/emacs-lsp/lsp-mode&quot;&gt;lsp-mode&lt;/a&gt; for ages, but with Emacs 29.1 including &lt;a href=&quot;https://joaotavora.github.io/eglot/&quot;&gt;Eglot&lt;/a&gt;, I decided to make the switch.&lt;/p&gt;

&lt;p&gt;In my Go project, I ran &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M-x eglot&lt;/code&gt; and was immediately met with an error:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;[eglot] Server reports (type=1): Error loading workspace folders (expected 1, got 0)
failed to load view for file:///path/to/my/project: err: go command required, not found: exec: &quot;go&quot;: executable file not found in $PATH: stderr: 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I’ve got Go installed in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/go&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/usr/local/go/bin&lt;/code&gt; is definitely in my &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exec-path&lt;/code&gt; variable in Emacs. It looked like Eglot wasn’t propagating &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exec-path&lt;/code&gt; down to its subprocesses. How annoying! I did a quick search through the list of Eglot-related variables and the Eglot documentation and no solution seemed immediately forthcoming.&lt;/p&gt;

&lt;p&gt;So I took the cheap way out and made a symlink. In my shell, I ran:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo ln&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;-sf&lt;/span&gt; /usr/local/go/bin/go /usr/local/bin/go
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is a dumb trick, and I am sure there is a better way to solve it. Do you know of one? Please comment and let me know!&lt;/p&gt;

&lt;h2 id=&quot;what-else&quot;&gt;What Else?&lt;/h2&gt;

&lt;p&gt;My exploration has revealed that there’s a lot of work left to do in the Emacs Tree-Sitter world. There are plenty of languages major modes that don’t yet have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ts-mode&lt;/code&gt; equivalent, and plenty of others that still need a lot of work.&lt;/p&gt;

&lt;p&gt;It’s too soon for me to say if this setup is preferrable to my previous configuration. But I am really looking forward to playing around with Eglot’s features and exploring the capabilities of Tree-Sitter.&lt;/p&gt;</content>
      </entry>
    
      <entry>
        
        <title>Pattern Matching and Tail Recursion in Emacs Lisp</title>
        <author>
          <name>Erik L. Arneson</name>
        </author>        
        <link href="https://arnesonium.com/2022/11/pattern-matching-tail-recursion-emacs-lisp" rel="alternate" type="text/html" title="Pattern Matching and Tail Recursion in Emacs Lisp" />
        <updated>2022-11-19T00:00:00+00:00</updated>
        <id>https://arnesonium.com/2022/11/tco-pattern-emacs-lisp</id>
          <category term="emacs" />
        
          <category term="programming" />
        
          <category term="emacs-lisp" />
        
          <category term="lisp" />
        <content type="html" xml:base="https://arnesonium.com/2022/11/pattern-matching-tail-recursion-emacs-lisp">&lt;p&gt;Functional programming offers a bunch of really cool programming patterns. Two that I really enjoy are &lt;a href=&quot;https://stackoverflow.com/questions/310974/what-is-tail-call-optimization&quot;&gt;tail recursion&lt;/a&gt; and &lt;a href=&quot;https://sodocumentation.net/ocaml/topic/2656/pattern-matching&quot;&gt;pattern matching&lt;/a&gt;, especially how they are implemented in OCaml. However, I spend a lot of time writing Emacs Lisp now, and I was wondering if I could find a way to use these patterns in that language.
&lt;!--more--&gt;&lt;/p&gt;

&lt;p&gt;It turns out that it is possible, thanks to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;named-let&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;. It isn’t as pretty and elegant as OCaml, but at least I get to keep excercising those parts of my programming brain. Maybe next I’ll try to figure out currying in Emacs Lisp.&lt;/p&gt;

&lt;p&gt;Note that this blog post includes some &lt;em&gt;really dumb&lt;/em&gt; examples, because that’s usually how I learn these things best.&lt;/p&gt;

&lt;h2 id=&quot;pattern-matching-with-pcase&quot;&gt;Pattern Matching with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Most programmers will be familiar with the granddaddy of pattern matching, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch/case&lt;/code&gt; construct. This is present in many, many programming languages, especially those in the ALGOL family.&lt;/p&gt;

&lt;p&gt;However, pattern matching can be so much more! Instead of simple equality checks, pattern matching extends the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;switch/case&lt;/code&gt; concept to include testing for all kinds of patterns and conditionals.&lt;/p&gt;

&lt;p&gt;Lisp programmers will already be familiar with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cond&lt;/code&gt;, which can be used to sequentially test for conditionals. However, functional language programmers have probably fallen in love with a more mature and sophisticated form of pattern matching that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cond&lt;/code&gt; doesn’t totally satisfy.&lt;/p&gt;

&lt;p&gt;Fortunately, Emacs Lisp has &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Pattern_002dMatching-Conditional.html&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;, the pattern-matching conditional&lt;/a&gt;. Here is an example of its use to duplicate &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;car&lt;/code&gt;, which is the dumbest possible example I could think of.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/car&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lst&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
     &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
     &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt; has a backquote syntax for matching various constructs, such as with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;`(,head . ,_)&lt;/code&gt; piece. This matches a cons cell and binds the CAR to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;head&lt;/code&gt; while ignoring the CDR.&lt;/p&gt;

&lt;p&gt;The next case is just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_&lt;/code&gt;, which is a catch-all matching operator.&lt;/p&gt;

&lt;p&gt;In the real world, you’d probably want some type checking and error correction, but I promised very simple examples. Check out the full range of &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/pcase-Macro.html&quot;&gt;matching capabilities for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;&lt;/a&gt;, and then &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote-Patterns.html&quot;&gt;read about all of the backquote patterns you can also use&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;tail-call-optimization-with-named-let&quot;&gt;Tail Call Optimization with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;named-let&lt;/code&gt;&lt;/h2&gt;

&lt;p&gt;Tail call optimization (TCO) is the programming language feature that allows efficient tail recursion without overflowing your stack. It is increasingly common in languages today, though from what I’ve seen, it always involves caveats.&lt;/p&gt;

&lt;p&gt;In Emacs Lisp, the easiest way to use TCO that I’ve come across is the &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Local-Variables.html#index-named_002dlet&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;named-let&lt;/code&gt; macro&lt;/a&gt;. With it, you define a function that can get “unrolled” inside another function. For example, here is a simple function that calculates a factorial using tail recursion.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/fact&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;in-num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;named-let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;rec-fact&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;in-num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;rec-fact&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
       &lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this example, you will notice that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rec-fact&lt;/code&gt; is the locally named function that gets called at the end of the first &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt; pattern. This is a tail call! It will get optimized.&lt;/p&gt;

&lt;p&gt;You can check this out by running something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(ela/fact 5)&lt;/code&gt; and getting 120 as the result. Try using a ridiculously big number and see if you get a stack overflow! You shouldn’t.&lt;/p&gt;

&lt;h2 id=&quot;another-example-summing-a-list&quot;&gt;Another Example: Summing a List&lt;/h2&gt;

&lt;p&gt;This is just a nostalgic example, since it’s probably the first tail recursive pattern matching function I ever wrote when learning OCaml a zillion years ago. This function will take a list of numbers and then add them all together. There are much better ways to write this in Emacs Lisp, like with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;named-let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sum-list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;lst&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;lst&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
       &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sum-list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
       &lt;span class=&quot;nv&quot;&gt;accu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can then call it like this:&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ela/sum&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And you will end up with exactly the result you expect. I was amused to see that the documentation page for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;named-let&lt;/code&gt; has a different implementation of this function that doesn’t use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Oh heck, let’s get fancy and rewrite &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply&lt;/code&gt; using this approach.&lt;/p&gt;

&lt;div class=&quot;language-elisp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;defun&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ela/apply&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;&amp;amp;rest&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;&quot;Apply FN to each element of ARGUMENTS and return the accumulated result.&quot;&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;;; Set up accumulator to the right type.&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;let*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;arguments-flat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;flatten-list&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;initial-value&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arguments-flat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pred&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;integerp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pred&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;stringp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))))&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;named-let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;apply-rec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;accumulator&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;initial-value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;input-list&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;arguments-flat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;pcase&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;input-list&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
         &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;apply-rec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;funcall&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fn&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;accumulator&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;tail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_&lt;/span&gt;
         &lt;span class=&quot;nv&quot;&gt;accumulator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I am certain this version of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;apply&lt;/code&gt; has bugs, but it works for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;concat&lt;/code&gt;, so that’s good enough for a simple example. And it uses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pcase&lt;/code&gt; twice!&lt;/p&gt;

&lt;p&gt;Hopefully this has been a useful blog post for somebody out there. Let me know in the comments if there are other fun things you have done with TCO and pattern matching in Emacs Lisp!&lt;/p&gt;</content>
      </entry>
    
</feed>
