<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>DefDel on James Oswald</title><link>http://jamesoswald.dev/series/defdel/</link><description>Recent content in DefDel on James Oswald</description><generator>Hugo</generator><language>en</language><lastBuildDate>Thu, 08 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="http://jamesoswald.dev/series/defdel/index.xml" rel="self" type="application/rss+xml"/><item><title>def∇: A Drop In def∇</title><link>http://jamesoswald.dev/posts/defdel2/</link><pubDate>Thu, 08 Oct 2026 00:00:00 +0000</pubDate><guid>http://jamesoswald.dev/posts/defdel2/</guid><description>&lt;p&gt;Yesterday I looked at &lt;code&gt;def∇&lt;/code&gt;, a macro for Dyalog APL like self-referencing functions in Lean.&lt;/p&gt;
&lt;div class="notice note"&gt;
 &lt;div class="notice-title"&gt;
 &lt;i class="fa-solid fa-sticky-note" aria-hidden="true"&gt;&lt;/i&gt;Note
 &lt;/div&gt;
 &lt;div class="notice-content"&gt;&lt;p&gt;Id like to thank my Lisp friend Armin for pointing out Lisp people have also been doing this since time immemorial, and pointing me to Paul Graham&amp;rsquo;s &lt;code&gt;alambda&lt;/code&gt; from his book &lt;em&gt;On Lisp&lt;/em&gt; where he does effectively the same thing in Common Lisp.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(defmacro alambda (parms &amp;amp;body body)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; `(labels ((self ,parms ,@body))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; #&amp;#39;self))
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;(alambda (n)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (if (&amp;gt; n 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; (cons n (self (- n 1))))) 
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;Unfortunately, after using that version of &lt;code&gt;def∇&lt;/code&gt; in practice in a huge project beyond the toy examples I gave yesterday, I quickly realized its largest limitation: it is not a drop in replacement. It turns the body of the definition into a &lt;code&gt;where&lt;/code&gt; helper, so proofs that rely on the original definition can break. The &lt;code&gt;∇&lt;/code&gt; in the body refers to that helper, which closes over the explicit binders rather than calling the function being defined.&lt;/p&gt;</description></item><item><title>def∇: An APL-Style Self Reference Macro for Lean4</title><link>http://jamesoswald.dev/posts/defdel/</link><pubDate>Wed, 07 Oct 2026 00:00:00 +0000</pubDate><guid>http://jamesoswald.dev/posts/defdel/</guid><description>&lt;p&gt;I’ve been writing recursive functions over syntax trees a lot recently. I also like my Lean code to be concise, but as things start piling up, this becomes harder and harder. Take the following function over propositional logic formulas as an example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-lean" data-lang="lean"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ff7b72"&gt;inductive&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Formula&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72"&gt;where&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;&lt;/span&gt;|&lt;span style="color:#6e7681"&gt; &lt;/span&gt;atom&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;String&lt;span style="color:#6e7681"&gt; &lt;/span&gt;→&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Formula&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;&lt;/span&gt;|&lt;span style="color:#6e7681"&gt; &lt;/span&gt;neg&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Formula&lt;span style="color:#6e7681"&gt; &lt;/span&gt;→&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Formula&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;&lt;/span&gt;|&lt;span style="color:#6e7681"&gt; &lt;/span&gt;conj&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Formula&lt;span style="color:#6e7681"&gt; &lt;/span&gt;→&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Formula&lt;span style="color:#6e7681"&gt; &lt;/span&gt;→&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Formula&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;&lt;/span&gt;&lt;span style="color:#ff7b72"&gt;def&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;depth&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;:&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Formula&lt;span style="color:#6e7681"&gt; &lt;/span&gt;→&lt;span style="color:#6e7681"&gt; &lt;/span&gt;Nat&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;&lt;/span&gt;|&lt;span style="color:#6e7681"&gt; &lt;/span&gt;.atom&lt;span style="color:#6e7681"&gt; &lt;/span&gt;_&lt;span style="color:#6e7681"&gt; &lt;/span&gt;=&amp;gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;1&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;&lt;/span&gt;|&lt;span style="color:#6e7681"&gt; &lt;/span&gt;.neg&lt;span style="color:#6e7681"&gt; &lt;/span&gt;c&lt;span style="color:#6e7681"&gt; &lt;/span&gt;=&amp;gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;1&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;+&lt;span style="color:#6e7681"&gt; &lt;/span&gt;depth&lt;span style="color:#6e7681"&gt; &lt;/span&gt;c&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e7681"&gt;&lt;/span&gt;|&lt;span style="color:#6e7681"&gt; &lt;/span&gt;.conj&lt;span style="color:#6e7681"&gt; &lt;/span&gt;c&lt;span style="color:#6e7681"&gt; &lt;/span&gt;d&lt;span style="color:#6e7681"&gt; &lt;/span&gt;=&amp;gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#a5d6ff"&gt;1&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;+&lt;span style="color:#6e7681"&gt; &lt;/span&gt;max&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;(&lt;/span&gt;depth&lt;span style="color:#6e7681"&gt; &lt;/span&gt;c&lt;span style="color:#ff7b72;font-weight:bold"&gt;)&lt;/span&gt;&lt;span style="color:#6e7681"&gt; &lt;/span&gt;&lt;span style="color:#ff7b72;font-weight:bold"&gt;(&lt;/span&gt;depth&lt;span style="color:#6e7681"&gt; &lt;/span&gt;d&lt;span style="color:#ff7b72;font-weight:bold"&gt;)&lt;/span&gt;&lt;span style="color:#6e7681"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;depth is recursive and &lt;code&gt;depth&lt;/code&gt; is used three times in its own definition. This is fine for small functions, but it can become cumbersome for larger ones. This is an actual function over description logic syntax from a codebase im working on. (You don&amp;rsquo;t need to understand the details to see thats A LOT of &lt;code&gt;polarize&lt;/code&gt; all all just to handle a pretty simple recursive traversal)&lt;/p&gt;</description></item></channel></rss>