<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<?xml-stylesheet type="text/xsl" href="/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Andrey Listopadov</title>
    <link>https://andreyor.st/categories/language-design/</link>
    <image>
      <title>Andrey Listopadov</title>
      <link>https://andreyor.st/categories/language-design/</link>
      <url>https://andreyor.st/categories/language-design/favicon-64.png</url>
    </image>
    <description>Posts from the 'language-design' category by Andrey Listopadov</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <copyright>Andrey Listopadov 2020-2026 - This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License</copyright>
    <lastBuildDate>Tue, 07 Apr 2026 02:47:00 +0300</lastBuildDate>
    <atom:link href="https://andreyor.st/categories/language-design/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Clojure on Fennel part one: Persistent Data Structures</title>
      <link>https://andreyor.st/posts/2026-04-07-clojure-on-fennel-part-one-persistent-data-structures/</link>
      <guid>https://andreyor.st/posts/2026-04-07-clojure-on-fennel-part-one-persistent-data-structures/</guid>
      <description>&lt;p&gt;Somewhere in 2019 I started a project that aimed to bring some of Clojure features to Lua runtime - &lt;a href=&#34;https://gitlab.com/andreyorst/fennel-cljlib&#34; target=&#34;_blank&#34;&gt;fennel-cljlib&lt;/a&gt;.
It was a library for Fennel that implemented a basic subset of &lt;code&gt;clojure.core&lt;/code&gt; namespace functions and macros.
My goal was simple - I enjoy working with Clojure, but I don&amp;rsquo;t use it for hobby projects, so I wanted Fennel to feel more Clojure-like, besides what it already provides for that.&lt;/p&gt;
&lt;p&gt;This library grew over the years, I implemented &lt;a href=&#34;https://andreyor.st/posts/2021-10-09-lazy-sequences-and-iterators/&#34;&gt;lazy sequences&lt;/a&gt;, added &lt;a href=&#34;https://gitlab.com/andreyorst/itable&#34; target=&#34;_blank&#34;&gt;immutability&lt;/a&gt;, made a &lt;a href=&#34;https://gitlab.com/andreyorst/fennel-test&#34; target=&#34;_blank&#34;&gt;testing library&lt;/a&gt;, inspired by &lt;code&gt;clojure.test&lt;/code&gt; and kaocha, and even made a &lt;a href=&#34;https://andreyor.st/posts/2023-05-15-clojures-coreasync-port-for-the-fennel-language/&#34;&gt;port of &lt;code&gt;clojure.core.async&lt;/code&gt;&lt;/a&gt;.
It was a passion project, I almost never used it to write actual software.
One notable exception is &lt;a href=&#34;https://gitlab.com/andreyorst/fenneldoc&#34; target=&#34;_blank&#34;&gt;fenneldoc&lt;/a&gt; - a tool for documentation generation for Fennel libraries.
And I haven&amp;rsquo;t seen anyone else use it for a serious project.&lt;/p&gt;
&lt;p&gt;The reason for that is simple - it was an experiment.
Corners were cut, and Fennel, being a Clojure-inspired lisp is not associated with functional programming the same way Clojure is.
As a matter of fact, I wouldn&amp;rsquo;t recommend using this library for anything serious&amp;hellip; yet.&lt;/p&gt;
&lt;p&gt;Recently, however, I started a new project: &lt;a href=&#34;https://gitlab.com/andreyorst/clojurefnl&#34; target=&#34;_blank&#34;&gt;ClojureFnl&lt;/a&gt;.
This is a Clojure-to-Fennel compiler that uses fennel-cljlib as a foundation.
It&amp;rsquo;s still in early days of development, but I&amp;rsquo;ve been working on it for a few months in private until I found a suitable way to make things work in March.
As of this moment, it is capable of compiling most of &lt;code&gt;.cljc&lt;/code&gt; files I threw at it, but running the compiled code is a different matter.
I mean, it works to some degree, but the support for standard library is far from done.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; Welcome to ClojureFnl REPL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ClojureFnl v0.0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; Fennel 1.6.1 on PUC Lua 5.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user=&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;prime?&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;some zero? &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;#(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;rem &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;%&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;range &lt;/span&gt;2 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;function&lt;/span&gt;&lt;span style=&#34;&#34;&gt;:&lt;/span&gt; 0&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x89ba7c550&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user=&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;range &lt;/span&gt;3 33 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:when&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;prime?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(3 5 7 11 13 17 19 23 29 31)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user=&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, there was a problem.&lt;/p&gt;
&lt;p&gt;My initial implementation of immutable data structures in the &lt;a href=&#34;https://gitlab.com/andreyorst/itable&#34; target=&#34;_blank&#34;&gt;itable&lt;/a&gt; library had a serious flaw.
The whole library was a simple hack based on the copy-on-write approach and a bunch of Lua metatables to enforce immutability.
As a result, all operations were extremely slow.
It was fine as an experiment, but if I wanted to go further with ClojureFnl, I had to replace it.
The same problem plagued &lt;a href=&#34;https://gitlab.com/andreyorst/immutableredblacktree.lua&#34; target=&#34;_blank&#34;&gt;immutableredblacktree.lua&lt;/a&gt;, an implementation of a copy-on-write red-black tree I made for sorted maps.
It did a full copy of the tree each time it was modified.&lt;/p&gt;
&lt;p&gt;For associative tables it wasn&amp;rsquo;t that big of a deal - usually maps contain a small amount of keys, and &lt;code&gt;itable&lt;/code&gt; only copied levels that needed to be changed.
So, if you had a map with, say, ten keys, and each of those keys contained another map with ten keys, adding, removing or updating a key in the outer map meant only copying these ten keys - not the whole nested map.
I could do that reliably, because inner maps were immutable too.&lt;/p&gt;
&lt;p&gt;But for arrays the story is usually quite different.
Arrays often store a lot of indices, and rarely are nested (or at least not as often as maps).
And copying arrays on every change quickly becomes expensive.
I&amp;rsquo;ve mitigated some of the performance problems by implementing my version of transients, however the beauty of Clojure&amp;rsquo;s data structures is that they&amp;rsquo;re quite fast even without this optimization.&lt;/p&gt;
&lt;h2 id=&#34;proper-persistent-data-structures&#34;&gt;Proper persistent data structures&lt;/h2&gt;
&lt;p&gt;Clojure uses Persistent HAMT as a base for its hash maps and sets, and a bit-partitioned trie for vectors.
For sorted maps and sets, Clojure uses an immutable red-black tree implementation, but as far as I know it&amp;rsquo;s not doing a full copy of the tree, and it also has structural sharing properties.&lt;/p&gt;
&lt;p&gt;I started looking into existing implementations of HAMT for Lua:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/raymond-w-ko/hamt.lua&#34; target=&#34;_blank&#34;&gt;hamt.lua&lt;/a&gt; (based on &lt;a href=&#34;https://github.com/mattbierner/hamt.git&#34; target=&#34;_blank&#34;&gt;mattbierner/hamt&lt;/a&gt;)
&lt;ul&gt;
&lt;li&gt;seemed incomplete&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://codeberg.org/alloyed/ltrie&#34; target=&#34;_blank&#34;&gt;ltrie&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;no transients&lt;/li&gt;
&lt;li&gt;no hashset&lt;/li&gt;
&lt;li&gt;no ordered map (expectable, different algorithm)&lt;/li&gt;
&lt;li&gt;no compound vector/hash&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://gist.github.com/SegFaultAX/3318559&#34; target=&#34;_blank&#34;&gt;Michael-Keith Bernard&amp;rsquo;s gist&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;no custom hashing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I could use one of those, notably &lt;code&gt;ltrie&lt;/code&gt; seemed the most appropriate one, but given that I&amp;rsquo;m working on a fennel library that I want later to embed into my Clojure compiler I needed a library implemented in Fennel.&lt;/p&gt;
&lt;p&gt;So I made my own library: &lt;a href=&#34;https://gitlab.com/andreyorst/immutable.fnl&#34; target=&#34;_blank&#34;&gt;immutable.fnl&lt;/a&gt;.
This library features HAMT-hash maps, hash-sets, and vectors, as well as a better implementation of a persistent red-black tree, and lazy linked lists.&lt;/p&gt;
&lt;h3 id=&#34;persistent-hash-map&#34;&gt;Persistent Hash Map&lt;/h3&gt;
&lt;p&gt;I started the implementation with a Persistent HAMT with native Lua hashing.
The data structure itself is a Hash Array Mapped Trie (HAMT) with 16-factor branching.
Thus all operations are O(Log16 N), which is effectively O(1) for a practical amount of keys.&lt;/p&gt;
&lt;p&gt;As far as I know, Clojure uses branching factor of 32, but for a Lua runtime this would mean that the popcount would be more expensive, and despite a shallower tree, each mutation would need to copy a larger sparse array.
With branching factor of 16 a map with 50K entries is ~4 levels deep, which would be ~3 with 32 branching factor.
So my logic was that it&amp;rsquo;ll be a compromise, especially since Lua is not JVM when it comes to performance.&lt;/p&gt;
&lt;p&gt;Of course, it&amp;rsquo;s not as fast as a pure Lua table, which is to be expected.
Lua tables are implemented in C, use efficient hashing, and dynamically re-allocated based on key count.
So for my implementation most operations are a lot slower, but the total time for an operation is still usable.&lt;/p&gt;
&lt;p&gt;Here are some benchmarks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Median time over 7 rounds (1 warmup discarded), N = 50000 elements.
GC stopped during measurement. Clock: os.clock (CPU).
Runtime: Fennel 1.7.0-dev on PUC Lua 5.5&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Regular operations are notably slower, when compared to Lua:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;Persistent HashMap&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 random keys&lt;/td&gt;
&lt;td&gt;2.05 ms&lt;/td&gt;
&lt;td&gt;164.80 ms&lt;/td&gt;
&lt;td&gt;80.3x slower&lt;/td&gt;
&lt;td&gt;3.3 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lookup 50000 random keys&lt;/td&gt;
&lt;td&gt;0.83 ms&lt;/td&gt;
&lt;td&gt;92.51 ms&lt;/td&gt;
&lt;td&gt;110.8x slower&lt;/td&gt;
&lt;td&gt;1.9 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete all&lt;/td&gt;
&lt;td&gt;0.78 ms&lt;/td&gt;
&lt;td&gt;170.78 ms&lt;/td&gt;
&lt;td&gt;219.8x slower&lt;/td&gt;
&lt;td&gt;3.4 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete 10%&lt;/td&gt;
&lt;td&gt;0.14 ms&lt;/td&gt;
&lt;td&gt;19.50 ms&lt;/td&gt;
&lt;td&gt;136.4x slower&lt;/td&gt;
&lt;td&gt;3.9 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iterate 50000 entries&lt;/td&gt;
&lt;td&gt;1.74 ms&lt;/td&gt;
&lt;td&gt;6.64 ms&lt;/td&gt;
&lt;td&gt;3.8x slower&lt;/td&gt;
&lt;td&gt;0.133 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;For transients the situation is a bit better, but not by much:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;Transient HashMap&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 random keys&lt;/td&gt;
&lt;td&gt;2.05 ms&lt;/td&gt;
&lt;td&gt;89.17 ms&lt;/td&gt;
&lt;td&gt;43.5x slower&lt;/td&gt;
&lt;td&gt;1.8 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete all&lt;/td&gt;
&lt;td&gt;0.76 ms&lt;/td&gt;
&lt;td&gt;104.31 ms&lt;/td&gt;
&lt;td&gt;138.0x slower&lt;/td&gt;
&lt;td&gt;2.1 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete 10%&lt;/td&gt;
&lt;td&gt;0.16 ms&lt;/td&gt;
&lt;td&gt;12.71 ms&lt;/td&gt;
&lt;td&gt;82.0x slower&lt;/td&gt;
&lt;td&gt;2.5 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;On LuaJIT numbers may seem worse, but per-operation cost is much lower, it&amp;rsquo;s just that native table operations are so much faster:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Median time over 7 rounds (1 warmup discarded), N = 50000 elements.
GC stopped during measurement. Clock: os.clock (CPU).
Runtime: Fennel 1.7.0-dev on LuaJIT 2.1.1774896198 macOS/arm64&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;Persistent HashMap&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 random keys&lt;/td&gt;
&lt;td&gt;0.86 ms&lt;/td&gt;
&lt;td&gt;49.05 ms&lt;/td&gt;
&lt;td&gt;56.8x slower&lt;/td&gt;
&lt;td&gt;0.981 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lookup 50000 random keys&lt;/td&gt;
&lt;td&gt;0.27 ms&lt;/td&gt;
&lt;td&gt;14.21 ms&lt;/td&gt;
&lt;td&gt;53.4x slower&lt;/td&gt;
&lt;td&gt;0.284 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete all&lt;/td&gt;
&lt;td&gt;0.13 ms&lt;/td&gt;
&lt;td&gt;48.63 ms&lt;/td&gt;
&lt;td&gt;374.1x slower&lt;/td&gt;
&lt;td&gt;0.973 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete 10%&lt;/td&gt;
&lt;td&gt;0.05 ms&lt;/td&gt;
&lt;td&gt;6.49 ms&lt;/td&gt;
&lt;td&gt;138.1x slower&lt;/td&gt;
&lt;td&gt;1.3 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iterate 50000 entries&lt;/td&gt;
&lt;td&gt;0.07 ms&lt;/td&gt;
&lt;td&gt;1.80 ms&lt;/td&gt;
&lt;td&gt;27.7x slower&lt;/td&gt;
&lt;td&gt;0.036 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;Transient HashMap&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 random keys&lt;/td&gt;
&lt;td&gt;0.76 ms&lt;/td&gt;
&lt;td&gt;22.43 ms&lt;/td&gt;
&lt;td&gt;29.6x slower&lt;/td&gt;
&lt;td&gt;0.449 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete all&lt;/td&gt;
&lt;td&gt;0.15 ms&lt;/td&gt;
&lt;td&gt;34.16 ms&lt;/td&gt;
&lt;td&gt;232.4x slower&lt;/td&gt;
&lt;td&gt;0.683 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete 10%&lt;/td&gt;
&lt;td&gt;0.04 ms&lt;/td&gt;
&lt;td&gt;5.02 ms&lt;/td&gt;
&lt;td&gt;132.1x slower&lt;/td&gt;
&lt;td&gt;1.0 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;With a branching factor of 32 the situation gets worse on PUC Lua, but is slightly better on LuaJIT.
So there&amp;rsquo;s still space for fine-tuning.&lt;/p&gt;
&lt;p&gt;For hashing strings and objects I decided to use &lt;code&gt;djb2&lt;/code&gt; algorithm.
I am almost as old as this hash function, so seemed like a good fit.
JK.
The main reason to use it was that it can be implemented even if we don&amp;rsquo;t have any bit-wise operators, and Lua doesn&amp;rsquo;t have them in all of the versions.
It only uses &lt;code&gt;+&lt;/code&gt;, &lt;code&gt;*&lt;/code&gt;, and &lt;code&gt;%&lt;/code&gt; arithmetic operators, so can be done on any Lua version.
It&amp;rsquo;s prone to collisions, and I try to mitigate that by randomizing it when the library is loaded.&lt;/p&gt;
&lt;p&gt;Still, collisions do happen, but HAMT core ensures that they will still resolve correctly by implementing a deep equality function for most objects.&lt;/p&gt;
&lt;p&gt;However, when first working on this, I noticed this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash-map&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;require &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:io.gitlab.andreyorst.immutable.PersistentHashMap&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local &lt;/span&gt;{&lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash&lt;/span&gt;} (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;require &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:io.gitlab.andreyorst.immutable.impl.hash&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash-map&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;161272824
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;161272824
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash-map&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash-map&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2) 1 {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2} 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2} 2}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is an interesting loophole. What object ended up in our hash map as a key - our persistent map or plain Lua table?
Well, that depends on insertion order:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;each &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;k&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;pairs &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash-map&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash-map&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2) 1 {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2} 2))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;getmetatable &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;k&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IPersistentHashMap&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;0&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x824d9b570&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;each &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;k&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;pairs &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash-map&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2} 2 (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;hash-map&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:foo&lt;/span&gt; 1 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bar&lt;/span&gt; 2) 1))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;getmetatable &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;k&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To &lt;em&gt;reiterate&lt;/em&gt;, I&amp;rsquo;m creating a hash map, with a key set to another persistent hash map, and then insert a plain Lua table with the same content.
The Lua table hashes to exactly the same hash, and goes into the same bucket, but there&amp;rsquo;s no collision, because &lt;em&gt;objects are equal by value&lt;/em&gt;.
But equality of mutable collections is very loosely defined - it may be equal right now, but the next time you look at it, it&amp;rsquo;s different.
So a different hashing was needed for persistent collections, to avoid these kinds of collision.
I ended up salting persistent collections with their prototype address in memory.&lt;/p&gt;
&lt;p&gt;Other than that, the HAMT implementation is by the book, and the rest is the interface for interacting with maps.&lt;/p&gt;
&lt;p&gt;Main operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new&lt;/code&gt; - construct a new map of key value pairs&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assoc&lt;/code&gt; - associate a key with a value&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dissoc&lt;/code&gt; - remove key from the map&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conj&lt;/code&gt; - universal method for association, much like in Clojure&lt;/li&gt;
&lt;li&gt;&lt;code&gt;contains&lt;/code&gt; - check if key is in the map&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count&lt;/code&gt; - map size, constant time&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get&lt;/code&gt; - get a key value from a map&lt;/li&gt;
&lt;li&gt;&lt;code&gt;keys&lt;/code&gt; - get a lazy list of keys&lt;/li&gt;
&lt;li&gt;&lt;code&gt;vals&lt;/code&gt; - get a lazy list of values&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transient&lt;/code&gt; - convert a map to a transient&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Coercion/conversion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;from&lt;/code&gt; - create a map from another object&lt;/li&gt;
&lt;li&gt;&lt;code&gt;to-table&lt;/code&gt; - convert a map to a Lua table&lt;/li&gt;
&lt;li&gt;&lt;code&gt;iterator&lt;/code&gt; - get an iterator to use in Lua loops&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Transient operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;assoc!&lt;/code&gt; - mutable &lt;code&gt;assoc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dissoc!&lt;/code&gt; - mutable &lt;code&gt;dissoc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;persistent&lt;/code&gt; - convert back to persistent variant, and mark transient as completed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This covers most of the needs in my &lt;code&gt;fennel-cljlib&lt;/code&gt; library, as anything besides it I can implement myself, or just adapt existing implementations.&lt;/p&gt;
&lt;p&gt;A Persistent Hash Set is also available as a thin wrapper around &lt;code&gt;PersistentHashMap&lt;/code&gt; with a few method changes.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A note on &lt;code&gt;PersistentArrayMap&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Clojure there is a second kind of maps that are ordered, not sorted, called a Persistent Array Map.
They are used by default when defining a map with eight keys or less, like &lt;code&gt;{:foo 1 :bar 2}&lt;/code&gt;.
The idea is simple - for such a small map, a linear search through all keys is faster than with a HAMT-based map.&lt;/p&gt;
&lt;p&gt;However, in my testing on the Lua runtime, there&amp;rsquo;s no benefit in this kind of a data structure, apart from it being an ordered variant.
Lookup is slower, because of a custom equality function, which does deep comparison.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;persistent-vector&#34;&gt;Persistent Vector&lt;/h3&gt;
&lt;p&gt;Persistent Vectors came next, and while the trie structure is similar to hash maps, vectors use direct index-based navigation instead of hashing, with a branching factor of 32.
Unlike maps, vector arrays in the HAMT are more densely packed, and therefore a higher branching factor is better for performance.
So lookup, update, and pop are O(log32 N), append can be considered O(1) amortized.&lt;/p&gt;
&lt;p&gt;Still, compared to plain Lua sequential tables the performance is not as good:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Median time over 7 rounds (1 warmup discarded), N = 50000 elements.
GC stopped during measurement. Clock: os.clock (CPU).
Runtime: Fennel 1.7.0-dev on PUC Lua 5.5&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;Persistent Vector&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 elements&lt;/td&gt;
&lt;td&gt;0.19 ms&lt;/td&gt;
&lt;td&gt;21.07 ms&lt;/td&gt;
&lt;td&gt;109.7x slower&lt;/td&gt;
&lt;td&gt;0.421 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lookup 50000 random indices&lt;/td&gt;
&lt;td&gt;0.47 ms&lt;/td&gt;
&lt;td&gt;14.05 ms&lt;/td&gt;
&lt;td&gt;29.7x slower&lt;/td&gt;
&lt;td&gt;0.281 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;update 50000 random indices&lt;/td&gt;
&lt;td&gt;0.32 ms&lt;/td&gt;
&lt;td&gt;70.04 ms&lt;/td&gt;
&lt;td&gt;221.6x slower&lt;/td&gt;
&lt;td&gt;1.4 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pop all 50000 elements&lt;/td&gt;
&lt;td&gt;0.25 ms&lt;/td&gt;
&lt;td&gt;24.34 ms&lt;/td&gt;
&lt;td&gt;96.2x slower&lt;/td&gt;
&lt;td&gt;0.487 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iterate 50000 elements&lt;/td&gt;
&lt;td&gt;0.63 ms&lt;/td&gt;
&lt;td&gt;10.16 ms&lt;/td&gt;
&lt;td&gt;16.2x slower&lt;/td&gt;
&lt;td&gt;0.203 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;Transient Vector&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000  elements&lt;/td&gt;
&lt;td&gt;0.19 ms&lt;/td&gt;
&lt;td&gt;7.81 ms&lt;/td&gt;
&lt;td&gt;40.3x slower&lt;/td&gt;
&lt;td&gt;0.156 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;update 50000 random indices&lt;/td&gt;
&lt;td&gt;0.33 ms&lt;/td&gt;
&lt;td&gt;20.76 ms&lt;/td&gt;
&lt;td&gt;62.4x slower&lt;/td&gt;
&lt;td&gt;0.415 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pop all 50000 elements&lt;/td&gt;
&lt;td&gt;0.25 ms&lt;/td&gt;
&lt;td&gt;11.14 ms&lt;/td&gt;
&lt;td&gt;44.4x slower&lt;/td&gt;
&lt;td&gt;0.223 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;On LuaJIT:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Median time over 7 rounds (1 warmup discarded), N = 50000 elements.
GC stopped during measurement. Clock: os.clock (CPU).
Runtime: Fennel 1.7.0-dev on LuaJIT 2.1.1774896198 macOS/arm64&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;Persistent Vector&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 elements&lt;/td&gt;
&lt;td&gt;0.10 ms&lt;/td&gt;
&lt;td&gt;7.62 ms&lt;/td&gt;
&lt;td&gt;74.0x slower&lt;/td&gt;
&lt;td&gt;0.152 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lookup 50000 random indices&lt;/td&gt;
&lt;td&gt;0.06 ms&lt;/td&gt;
&lt;td&gt;0.67 ms&lt;/td&gt;
&lt;td&gt;11.8x slower&lt;/td&gt;
&lt;td&gt;0.013 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;update 50000 random indices&lt;/td&gt;
&lt;td&gt;0.04 ms&lt;/td&gt;
&lt;td&gt;29.13 ms&lt;/td&gt;
&lt;td&gt;710.4x slower&lt;/td&gt;
&lt;td&gt;0.583 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pop all 50000 elements&lt;/td&gt;
&lt;td&gt;0.02 ms&lt;/td&gt;
&lt;td&gt;8.62 ms&lt;/td&gt;
&lt;td&gt;410.4x slower&lt;/td&gt;
&lt;td&gt;0.172 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iterate 50000 elements&lt;/td&gt;
&lt;td&gt;0.02 ms&lt;/td&gt;
&lt;td&gt;0.57 ms&lt;/td&gt;
&lt;td&gt;28.7x slower&lt;/td&gt;
&lt;td&gt;0.011 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;Transient Vector&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 elements&lt;/td&gt;
&lt;td&gt;0.05 ms&lt;/td&gt;
&lt;td&gt;0.59 ms&lt;/td&gt;
&lt;td&gt;11.6x slower&lt;/td&gt;
&lt;td&gt;0.012 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;update 50000 random indices&lt;/td&gt;
&lt;td&gt;0.04 ms&lt;/td&gt;
&lt;td&gt;2.06 ms&lt;/td&gt;
&lt;td&gt;51.6x slower&lt;/td&gt;
&lt;td&gt;0.041 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;pop all 50000 elements&lt;/td&gt;
&lt;td&gt;0.02 ms&lt;/td&gt;
&lt;td&gt;0.84 ms&lt;/td&gt;
&lt;td&gt;46.7x slower&lt;/td&gt;
&lt;td&gt;0.017 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;I think this is an OK performance still.
Vectors don&amp;rsquo;t use hashing, instead it is a direct index traversal via bit-shifting, so there&amp;rsquo;s no hashing, just index math.&lt;/p&gt;
&lt;p&gt;Operations on vectors include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;new&lt;/code&gt; - constructor&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conj&lt;/code&gt; - append to the tail&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assoc&lt;/code&gt; - change a value at given index&lt;/li&gt;
&lt;li&gt;&lt;code&gt;count&lt;/code&gt; - element count (constant time)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get&lt;/code&gt; - get value at given index&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pop&lt;/code&gt; - remove last&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transient&lt;/code&gt; - convert to a transient&lt;/li&gt;
&lt;li&gt;&lt;code&gt;subvec&lt;/code&gt; - create a slice of the vector in constant time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Transient operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;assoc!&lt;/code&gt; - mutable &lt;code&gt;assoc&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;conj!&lt;/code&gt; - mutable &lt;code&gt;conj&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pop!&lt;/code&gt; - mutable &lt;code&gt;pop&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;persistent&lt;/code&gt; - convert back to persistent and finalize&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Interop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;from&lt;/code&gt; - creates a vector from any other collection&lt;/li&gt;
&lt;li&gt;&lt;code&gt;iterator&lt;/code&gt; - returns an iterator for use in Lua loops&lt;/li&gt;
&lt;li&gt;&lt;code&gt;to-table&lt;/code&gt; - converts to a sequential Lua table&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One notable difference in both vector and hash-map is that it allows &lt;code&gt;nil&lt;/code&gt; to be used as a value (and as a key, in case of the hash-map).
Vectors don&amp;rsquo;t have the same problem that Lua sequential tables have, where length is not well-defined if the table has holes in it.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a debate for another time, whether allowing &lt;code&gt;nil&lt;/code&gt; as a value (and especially as a key) is a good decision to make, but Clojure already made it for me.
So for this project I decided to support it.&lt;/p&gt;
&lt;h3 id=&#34;persistent-red-black-tree&#34;&gt;Persistent Red-Black Tree&lt;/h3&gt;
&lt;p&gt;For sorted maps and sorted sets I chose Okasaki&amp;rsquo;s insertion and Germane &amp;amp; Might&amp;rsquo;s deletion algorithms.
Most of the knowledge I got from this amazing &lt;a href=&#34;https://matt.might.net/articles/red-black-delete/&#34; target=&#34;_blank&#34;&gt;blog post&lt;/a&gt; by Matt Might.&lt;/p&gt;
&lt;p&gt;I believe the operations are O(Log N), as for any binary tree, but given that the deletion algorithm is tricky, I&amp;rsquo;m not exactly sure:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Median time over 7 rounds (1 warmup discarded), N = 50000 elements.
GC stopped during measurement. Clock: os.clock (CPU).
Runtime: Fennel 1.7.0-dev on PUC Lua 5.5&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;PersistentTreeMap&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 random keys&lt;/td&gt;
&lt;td&gt;2.10 ms&lt;/td&gt;
&lt;td&gt;209.23 ms&lt;/td&gt;
&lt;td&gt;99.8x slower&lt;/td&gt;
&lt;td&gt;4.2 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lookup 50000 random keys&lt;/td&gt;
&lt;td&gt;0.88 ms&lt;/td&gt;
&lt;td&gt;82.97 ms&lt;/td&gt;
&lt;td&gt;94.2x slower&lt;/td&gt;
&lt;td&gt;1.7 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete all&lt;/td&gt;
&lt;td&gt;0.74 ms&lt;/td&gt;
&lt;td&gt;173.76 ms&lt;/td&gt;
&lt;td&gt;234.8x slower&lt;/td&gt;
&lt;td&gt;3.5 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;On LuaJIT:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Median time over 7 rounds (1 warmup discarded), N = 50000 elements.
GC stopped during measurement. Clock: os.clock (CPU).
Runtime: Fennel 1.7.0-dev on LuaJIT 2.1.1774896198 macOS/arm64&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Lua table&lt;/th&gt;
&lt;th&gt;PersistentTreeMap&lt;/th&gt;
&lt;th&gt;Ratio&lt;/th&gt;
&lt;th&gt;per op&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;insert 50000 random keys&lt;/td&gt;
&lt;td&gt;0.72 ms&lt;/td&gt;
&lt;td&gt;101.08 ms&lt;/td&gt;
&lt;td&gt;140.4x slower&lt;/td&gt;
&lt;td&gt;2.0 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;lookup 50000 random keys&lt;/td&gt;
&lt;td&gt;0.25 ms&lt;/td&gt;
&lt;td&gt;12.67 ms&lt;/td&gt;
&lt;td&gt;49.9x slower&lt;/td&gt;
&lt;td&gt;0.253 us&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;delete all&lt;/td&gt;
&lt;td&gt;0.14 ms&lt;/td&gt;
&lt;td&gt;56.14 ms&lt;/td&gt;
&lt;td&gt;403.9x slower&lt;/td&gt;
&lt;td&gt;1.1 us&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The API for sorted maps and sets is the same as to their hash counterparts with a small difference - no transients.
Clojure doesn&amp;rsquo;t do them, and I&amp;rsquo;m not doing them too.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s all for benchmarks.
I know that there are many problems with this kind of benchmarking, so take it with a grain of salt.
Still, the results are far, far better than what I had with &lt;code&gt;itable&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But there are two more data structures to talk about.&lt;/p&gt;
&lt;h3 id=&#34;persistent-list&#34;&gt;Persistent List&lt;/h3&gt;
&lt;p&gt;As I mentioned, I made a lazy persistent list implementation a while ago but it had its problems and I couldn&amp;rsquo;t integrate that library with the current one well enough.&lt;/p&gt;
&lt;p&gt;The main problem was that this library uses a single shared metatable per data structure, and the old implementation of lazy lists didn&amp;rsquo;t.
This difference makes it hard to check whether the object is a table, hash-map, list, vector, set, etc.
So I reimplemented them.&lt;/p&gt;
&lt;p&gt;The reason for old implementation to use different metatables was because I decided to try the approach described in &lt;a href=&#34;https://aphyr.com/posts/340-reversing-the-technical-interview&#34; target=&#34;_blank&#34;&gt;Reversing the technical interview&lt;/a&gt; post by Kyle Kingsbury (Aphyr).
I know this post is more of a fun joke, but it actually makes sense to define linked lists like that in Lua.&lt;/p&gt;
&lt;p&gt;See, tables are mutable, and you can&amp;rsquo;t do much about it.
Closures, on the other hand are much harder to mutate - you can still do it via the &lt;code&gt;debug&lt;/code&gt; module, but it&amp;rsquo;s hard, and it&amp;rsquo;s not always present.
So storing &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt; in function closures was a deliberate choice.&lt;/p&gt;
&lt;p&gt;However, it meant that I needed to somehow attach metadata to the function, to make it act like a data structure, and you can&amp;rsquo;t just use &lt;code&gt;setmetatable&lt;/code&gt; on a function.
Again, you can do &lt;code&gt;debug.setmetatable&lt;/code&gt; but all function objects share the same metadata table.
So, while you can do fancy things like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;comp&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;...&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;g&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;...&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;function&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;0&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x7bdb320a0&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;debug.setmetatable &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;[]) {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:__add&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;comp&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;function&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;: &lt;/span&gt;0&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;x7bd17f040&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;gt;&amp;gt;&lt;/span&gt; ((&lt;span style=&#34;font-weight:bold&#34;&gt;+ &lt;/span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;string.reverse &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;string.upper&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OOF&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can also notice, that our &lt;code&gt;+&lt;/code&gt; overload applied to functions in the string module.&lt;/p&gt;
&lt;p&gt;So instead, we use a table, and wrap it with a metatable that has a &lt;code&gt;__call&lt;/code&gt; metamethod, essentially making our table act like a function.
This, in turn means, that we have to create two tables per list node - one to give to the user, the other to set our &lt;code&gt;__call&lt;/code&gt; and use it as a meta-table.&lt;/p&gt;
&lt;p&gt;Convoluted, I know.
It&amp;rsquo;s all in the past now - current implementation is a simple &lt;code&gt;{:head 42 :tail {...}}&lt;/code&gt; table.
Not sure what is worse.&lt;/p&gt;
&lt;p&gt;But that meant that I had to rework how lazy lists worked, because previously it was just a metatable swap.
Now list stores a &amp;ldquo;thunk&amp;rdquo;, that when called replaces itself in the node with the &lt;code&gt;:head&lt;/code&gt; and &lt;code&gt;:tail&lt;/code&gt; keys.
Unless it&amp;rsquo;s an empty list, of course - in that case we swap the metatable to an empty list one.&lt;/p&gt;
&lt;p&gt;So Lists have three metatables now:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;IPersistentList&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IPersistentList$Empty&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;IPersistentList$Lazy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Instead of god knows how many in the old implementation.&lt;/p&gt;
&lt;p&gt;The list interface is also better now.
Previously it was hardcoded how to construct a list from a data structure.
Current implementation also hardcodes it, but also allows to build a list in a lazy way from an iterator.&lt;/p&gt;
&lt;p&gt;This is better, because now a custom data structure that has weird iteration schema (like maps and sets in this library), we still can convert it to a list.
A general case is just:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-fennel&#34; data-lang=&#34;fennel&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;PersistentList.from-iterator&lt;/span&gt; #(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;pairs &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;data&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;v&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Meaning that we pass a function that will produce the iterator, and a function to capture values from that iterator.
Reminds me of clojure transducers in some way.&lt;/p&gt;
&lt;h3 id=&#34;persistent-queue&#34;&gt;Persistent Queue&lt;/h3&gt;
&lt;p&gt;And the final data structure - a persistent queue.
Fast append at the end, and also fast remove from the front.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s done by holding two collections - a linked list at the front, and a persistent vector for the rear.
So removing from the list is O(1), and appending to the vector is also pretty much O(1).&lt;/p&gt;
&lt;p&gt;Interesting things start to happen when we exhaust the list part - we need to move vector&amp;rsquo;s contents into the list.
It is done by calling &lt;code&gt;PersistentList.from&lt;/code&gt; on the rear.
And building a list out of a persistent vector is an O(1) operation as well!
Well, because nothing happens, we simply create an iterator, and build the list in a lazy way.
But since indexing the vector is essentially ~O(1), we can say that we still retain this property.&lt;/p&gt;
&lt;p&gt;Or at least that&amp;rsquo;s how I reasoned about this - I&amp;rsquo;m not that good with time-complexity stuff.&lt;/p&gt;
&lt;h2 id=&#34;clojurefnl&#34;&gt;ClojureFnl&lt;/h2&gt;
&lt;p&gt;That concludes part one about ClojureFnl.&lt;/p&gt;
&lt;p&gt;I know that this post was not about ClojureFnl at all, but I had to fix my underlying implementation first.
Now, that I have better data structures to build from, I can get back working on the compiler itself.
So the next post will hopefully be about the compiler itself.&lt;/p&gt;
&lt;p&gt;Unless I get distracted again.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Clojure on Fennel part one: Persistent Data Structures&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Tue, 07 Apr 2026 02:47:00 +0300</pubDate>
    </item><item>
      <title>Thoughts on Crafting Interpreters - Part 3</title>
      <link>https://andreyor.st/posts/2024-01-25-thoughts-on-crafting-interpreters-part-3/</link>
      <guid>https://andreyor.st/posts/2024-01-25-thoughts-on-crafting-interpreters-part-3/</guid>
      <description>&lt;p&gt;The unexpected part!&lt;/p&gt;
&lt;p&gt;I liked hacking on Lox in Zig a lot, so I decided it would be great to make some changes to the language.
It should be good for a better understanding of the book&amp;rsquo;s material, and probably will be a lot of fun!&lt;/p&gt;
&lt;h2 id=&#34;minor-changes-from-the-book&#34;&gt;Minor changes from the book&lt;/h2&gt;
&lt;p&gt;I looked back on what we&amp;rsquo;ve done in the book and decided to do some tweaking.&lt;/p&gt;
&lt;p&gt;First, I made &lt;code&gt;print&lt;/code&gt; to be a function and not a statement.
Making it a statement was understandable, as there was no way to call anything in the language yet, and in order to see some evaluation results &lt;code&gt;print&lt;/code&gt; statement was introduced.
Changing it to be a function has some benefits.&lt;/p&gt;
&lt;p&gt;First, we can pass more than one argument, and automatically concatenate those with a space.
It&amp;rsquo;s not the same as &lt;code&gt;printf&lt;/code&gt; in C, and with other functions that accept format strings in various languages, but still handy:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(1, 2, 3) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// prints: 1 2 3\n
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Secondly, we can pass it as a callback to other functions, which can&amp;rsquo;t be done with statements.
Lox isn&amp;rsquo;t a real-world language, so this isn&amp;rsquo;t something that people will probably want to be able to do, but still, it&amp;rsquo;s an advantage over &lt;code&gt;print&lt;/code&gt; being a statement.&lt;/p&gt;
&lt;p&gt;Speaking of passing functions - why are there no lambdas in the book?
IIRC, the first half had a &amp;ldquo;Challenge&amp;rdquo;, for implementing a support of anonymous functions, and in the second half, there was none.
It&amp;rsquo;s not like it&amp;rsquo;s hard either.
I added two possible ways to define an anonymous function.&lt;/p&gt;
&lt;p&gt;The first one has exactly the same syntax as a named function, except you don&amp;rsquo;t specify the name:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fun (x, y, z) { &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; x + y + z; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can assign this expression to a variable, or call it immediately:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; var foo = fun (x, y, z) { return x + y + z; };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; return foo(1, 2, 3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; return (fun (x, y, z) { return x + y + z; })(4, 5, 6);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;15
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But it&amp;rsquo;s too verbose, so I added another syntax using a backslash:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; var bar = \x,y,z -&amp;gt; x + y + z;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; return bar(1,2,3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;6
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; return (\x,y,z-&amp;gt;x+y+z)(4,5,6);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;15
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s a bit terse, and I&amp;rsquo;m not sure if I like it or not, but it works.&lt;/p&gt;
&lt;p&gt;Speaking of backslashes - the book doesn&amp;rsquo;t deal with string escaping at all.
I understand that dealing with it is kinda tricky - you need to escape quotes, escape the already escaped quotes and escape characters, you need to correctly unescape everything when printing, etc.
So it being omitted from the book is OK, I guess, but I decided to implement this in the parser and in the &lt;code&gt;tostring&lt;/code&gt; function that I added as one of the book&amp;rsquo;s &amp;ldquo;Challenges&amp;rdquo;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; return &amp;#34;\&amp;#34;foo\&amp;#34;&amp;#34;; // nested strings can be escaped
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;#34;\&amp;#34;foo\&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; print(&amp;#34;\&amp;#34;foo\&amp;#34;&amp;#34;); // printing correctly unescapes everything
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;#34;foo&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This will play nice with changes I&amp;rsquo;ll describe a bit later.&lt;/p&gt;
&lt;p&gt;As a part of another &lt;a href=&#34;http://craftinginterpreters.com/a-virtual-machine.html#challenges&#34; target=&#34;_blank&#34;&gt;&amp;ldquo;Challenge&amp;rdquo;&lt;/a&gt;, I changed the virtual machine in such a way that it avoids consecutive popping and pushing in most of the instructions where possible.
This was supposed to make the VM slightly faster, however, it did not have any effect on speed, at least how I measured it.&lt;/p&gt;
&lt;p&gt;Finally, I decided to add the &lt;code&gt;type&lt;/code&gt; function, so the user will be able to tell what kind of an object the function received.
This will play nicely with what I will talk about a bit later.&lt;/p&gt;
&lt;h2 id=&#34;objects-gone&#34;&gt;Objects gone&lt;/h2&gt;
&lt;p&gt;As you may remember, in my previous post on the topic of this book I &lt;a href=&#34;https://andreyor.st/posts/2024-01-15-thoughts-on-crafting-interpreters-part-2/#classes-and-instances&#34;&gt;said&lt;/a&gt; that I don&amp;rsquo;t want to implement classes, and instead would prefer more general hash tables.
And, I also mentioned that the lack of arrays is a strange decision, that limits language capabilities quite heavily.
So I decided to implement data structures!&lt;/p&gt;
&lt;h2 id=&#34;arrays&#34;&gt;Arrays&lt;/h2&gt;
&lt;p&gt;The first data structure I added was arrays.
Adding arrays was easy enough so I still think it is weird that the book doesn&amp;rsquo;t mention them at all.&lt;/p&gt;
&lt;p&gt;First, I needed a few new instructions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; OPCode = &lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;(Code) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    Array,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    SetIndex,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    GetIndex,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    InvokeFromArray,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I chose to implement the syntax for indexing arrays as in most languages, i.e. &lt;code&gt;array[index]&lt;/code&gt;.
Similarly to how we did with invoking instances, I added other instructions for calling array indexes directly: &lt;code&gt;array[index](args)&lt;/code&gt;.
It&amp;rsquo;s a minor optimization, but I wanted to do it to better grasp it.
This meant that in the scanner I had to implement two new tokens:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;--- a/src/zig/lox/scanner.zig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+++ b/src/zig/lox/scanner.zig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; TokenType = &lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    LEFT_BRACKET,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    RIGHT_BRACKET,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// in the scanner&amp;#39;s switch statement:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (c) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;[&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.makeToken(.LEFT_BRACKET),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;]&amp;#39;&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.makeToken(.RIGHT_BRACKET),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the compiler, these tokens receive a prefix and infix parse rules:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; makeRules() []ParseRule {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.LEFT_BRACKET)] = .{ .prefix = Parser.array, .infix = Parser.arrayIndex, .precedence = .CALL };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.RIGHT_BRACKET)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Rules themselves are simple:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Parser = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; arrayIndex(self: *Parser, canAssign: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;) LoxError!&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.RIGHT_BRACKET, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;]&amp;#39; after an index.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (canAssign &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.match(.EQUAL)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.SetIndex));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.match(.LEFT_PAREN)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; argCount = &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.argumentList();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.InvokeFromArray));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitByte(argCount);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.GetIndex));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; array(self: *Parser, _: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;) LoxError!&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; elemCount: Code = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!self.check(.RIGHT_BRACKET) &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; !self.check(.EOF)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; do = &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (do &lt;span style=&#34;font-weight:bold&#34;&gt;or&lt;/span&gt; self.match(.COMMA)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                do = &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                elemCount += 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (elemCount == 255)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    self.error_(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Can&amp;#39;t have more than 255 array elements.&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.RIGHT_BRACKET, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;]&amp;#39; after expressions.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; arr = (&lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; Array.new(self.vm, elemCount)).obj.asValue();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitBytes(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Array), &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.makeConstant(arr));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitByte(elemCount);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, onto the object itself.&lt;/p&gt;
&lt;p&gt;First, I added the new struct, called &lt;code&gt;Array&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Array = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Self = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@This&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    obj: Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    values: ArrayList(Value),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; new(vm: *VM, capacity: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;) LoxError!*Self {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; obj = &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; Obj.allocate(vm, Self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; out = obj.as(Self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        out.* = Self{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .obj = obj.*,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .values = ArrayList(Value).initCapacity(vm.allocator, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@max&lt;/span&gt;(4, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(capacity)))) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; LoxError.OutOfMemoryError,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; out;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; destroy(self: *Self, vm: *VM) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.values.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        vm.allocator.destroy(self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; markValues(self: *Self, vm: *VM) !&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (self.values.items) |value| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; value.mark(vm);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; equal(self: *Self, other: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.values.items.len != other.values.items.len) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (self.values.items, 0..) |item, i| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!item.equal(other.values.items[i])) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, it&amp;rsquo;s basically a thin wrapper around the &lt;code&gt;ArrayList&lt;/code&gt; from Zig&amp;rsquo;s standard library.&lt;/p&gt;
&lt;p&gt;I also implemented the equality semantics.
If array lengths are equal and all elements of both arrays are equal then the arrays are equal.
We don&amp;rsquo;t do the deep comparison if arrays are the same objects.
Pretty standard stuff.&lt;/p&gt;
&lt;p&gt;In the VM, creating the array is straightforward:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; op: OPCode = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@enumFromInt&lt;/span&gt;(frame.readByte());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (op) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    .Array =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; arr = frame.readConstant().as(*Array);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; valueCount = frame.readByte();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (0..valueCount) |i| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            arr.values.append((self.stackTop - (valueCount - i))[0]) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OOME: can&amp;#39;t append to array&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.stackTop -= valueCount;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.push(arr.obj.asValue());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Maybe a bit sub-optimal, but we had to do it now, as expressions are not always constant.&lt;/p&gt;
&lt;h2 id=&#34;tables&#34;&gt;Tables&lt;/h2&gt;
&lt;p&gt;A.K.A. dictionaries, hash maps, key-value storage, etc.&lt;/p&gt;
&lt;p&gt;I have a firm belief, that an object is just a special case of a hash map, and not vice-versa.
With closures, anonymous functions, and hash maps we can implement objects and most of their properties without resorting to making it a part of the language.
Well, if we want this to be really efficient, it is probably better to make it part of the language, but I don&amp;rsquo;t care about OOP code efficiency, or OOP at all for that matter.
So I removed all of the code that was related to instances, classes, and objects, and replaced it with a third of the code needed to implement hash tables.&lt;/p&gt;
&lt;p&gt;Same as arrays, hash tables required new syntax.
I decided to do it his way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;bar&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;baz&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;=&amp;gt;&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;qux&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;wax&amp;#34;&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Additionally, string keys can be written as &lt;code&gt;.key&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;#{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.foo&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;bar&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;.baz&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;=&amp;gt;&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;qux&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;wax&amp;#34;&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This matches the key access &lt;code&gt;dict.key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Implementing this syntax required adding another character to the scanner:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -253,6 +242,7 @@ pub const Scanner = struct {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+            &amp;#39;#&amp;#39; =&amp;gt; return self.makeToken(.HASH),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And a new parse rule in the compiler:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; makeRules() []ParseRule {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.HASH)] = .{ .prefix = Parser.hashTable, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The rule is again quite simple:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; hashTable(self: *Parser, _: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;) LoxError!&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.LEFT_BRACE, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;{&amp;#39; before table body.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; kvCount: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (!self.check(.RIGHT_BRACE) &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; !self.check(.EOF)) : (kvCount += 2) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.match(.DOT)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                self.consume(.IDENTIFIER, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect property name after &amp;#39;.&amp;#39;.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; s = &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; String.copy(self.vm, self.previous.name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitConstant(s.obj.asValue());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.consume(.FAT_ARROW, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;=&amp;gt;&amp;#39; after key expression.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!self.check(.RIGHT_BRACE) &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; !self.check(.EOF))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                self.consume(.COMMA, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;,&amp;#39; after value expression.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.RIGHT_BRACE, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;}&amp;#39; after table body.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (kvCount % 2 != 0) self.error_(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Missing value expression&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (kvCount &amp;gt; 255) self.error_(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;too many key-value expressions&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; table = (&lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; HashTable.new(self.vm)).obj.asValue();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitBytes(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Table), &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.makeConstant(table));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(kvCount));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In the VM it&amp;rsquo;s again, pretty straightforward:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; op: OPCode = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@enumFromInt&lt;/span&gt;(frame.readByte());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (op) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    .Table =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; table = frame.readConstant().as(*HashTable);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; valueCount = frame.readByte();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; i = valueCount;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (i &amp;gt; 0) : (i -= 2) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; slot = (self.stackTop - i);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _ = table.fields.set(slot[0], slot[1]) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OOME: can&amp;#39;t append to array&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.stackTop -= valueCount;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.push(table.obj.asValue());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Array indexing also replaced the &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt; functions for tables:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; tbl = &lt;span style=&#34;&#34;&gt;#&lt;/span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;foo bar&amp;#34;&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;baz&amp;#34;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; key = &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;foo bar&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// before:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;get(tbl, key); &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// &amp;#34;baz&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;set(tbl, key, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;qux&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// now:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;tbl[key]; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// &amp;#34;baz&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;tbl[key] = &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;qux&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Perhaps a bit unconventional to be able to use array indexing on tables, but I find this OK.&lt;/p&gt;
&lt;p&gt;In addition to hash tables, I added hash sets:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; set = &lt;span style=&#34;&#34;&gt;#&lt;/span&gt;[&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;bar&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;baz&amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I thought about using &lt;code&gt;#{}&lt;/code&gt; syntax as in Clojure, but it meant that I needed to choose what data structure to use once I met any of the keys and decide what was a syntactic error and what wasn&amp;rsquo;t.
For example, is it an incorrect hash set or an incorrect hash map?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;&#34;&gt;#&lt;/span&gt;{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;foo&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;baz&amp;#34;&lt;/span&gt; =&amp;gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;qux&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Perhaps, it was meant to be a hash set, but was confused and added &lt;code&gt;=&amp;gt;&lt;/code&gt; between the elements, because it has the same syntax.
Then the error something like &lt;code&gt;&amp;quot;unexpected token &#39;=&amp;gt;&#39; in the hash set literal&amp;quot;&lt;/code&gt; would be the correct one.
Or, if the programmer wanted a hash map and just forgot to add a value for the first key, then the error would be confusing.
So I chose &lt;code&gt;#[]&lt;/code&gt; instead.&lt;/p&gt;
&lt;h2 id=&#34;multiple-value-returns&#34;&gt;Multiple value returns&lt;/h2&gt;
&lt;p&gt;That was a feature I wanted to add, but couldn&amp;rsquo;t find a suitable way of doing it.&lt;/p&gt;
&lt;p&gt;One thing I don&amp;rsquo;t like about Lua is how it implemented multiple value returns.
It has a lot of gotchas, and when something in the language has a gotcha it&amp;rsquo;s a bad thing in my opinion.
You can read &lt;a href=&#34;https://benaiah.me/posts/everything-you-didnt-want-to-know-about-lua-multivals/&#34; target=&#34;_blank&#34;&gt;this article&lt;/a&gt; for a lot of interesting examples, so I&amp;rsquo;ll keep it brief here.&lt;/p&gt;
&lt;p&gt;For example, here&amp;rsquo;s a function that returns several values:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;foo&lt;/span&gt; ()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; 1, 2, 3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can call a function that accepts multiple values, and pass it the result of calling this function, for example, &lt;code&gt;print&lt;/code&gt; is one such function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(foo()) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- prints 1	2	3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can prepend more arguments before the call to &lt;code&gt;foo&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(0, foo()) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- prints 0	1	2	3&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But we can&amp;rsquo;t do the same after the call to &lt;code&gt;foo&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print(foo(), 4) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- prints 1	4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s a gotcha, and it often hits people when they use &lt;code&gt;table.insert&lt;/code&gt; in combination with some function that can return multiple values.
For example, &lt;code&gt;string.gsub&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; words = {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;world&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; capitalized_words = {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; _, word &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; pairs(words) &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   table.insert(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      capitalized_words,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      string.gsub(word, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;^%l&amp;#34;&lt;/span&gt;, string.upper)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   )
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If we execute this code, we&amp;rsquo;ll get the following error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bad argument #2 to &amp;#39;insert&amp;#39; (number expected, got string)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Why?
Because &lt;code&gt;string.gsub&lt;/code&gt; returns the string and then the index where the replacement occurred.
And table insert accepts a table, index, and a new value: &lt;code&gt;table.insert(t, 3, &amp;quot;foo&amp;quot;)&lt;/code&gt;.
You can omit the index, and just supply the value like this &lt;code&gt;table.insert(t, &amp;quot;foo&amp;quot;)&lt;/code&gt; and the value will be inserted as the last in the table.
In other words, it&amp;rsquo;s the same as &lt;code&gt;table.insert(t, #t, &amp;quot;foo&amp;quot;)&lt;/code&gt;.
When we pass &lt;code&gt;string.gsub&lt;/code&gt; as the expression that should produce a value, it actually returns two values, and &lt;code&gt;table.insert&lt;/code&gt; thinks that we use it&amp;rsquo;s three-argument arity and fails.&lt;/p&gt;
&lt;p&gt;There are many more gotchas to multiple values than that, and the most annoying one perhaps is that you can&amp;rsquo;t store them in a variable to create a closure.
You have to create a table with your variadic arguments if you want to use them in some other inner function.
In other words, this code is invalid:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt;(...)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print(...)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get this error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;cannot use &amp;#39;...&amp;#39; outside a vararg function near &amp;#39;...&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Instead, we need to do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt;(...)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- or use table.pack(...) in lua 5.2 and above&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;local&lt;/span&gt; va = {n=select(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt;, ...) ...}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;-- unpack was moved to table.unpack in Lua 5.2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print((table.unpack &lt;span style=&#34;font-weight:bold&#34;&gt;or&lt;/span&gt; unpack)(va, 1, va.n))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This has a performance penalty, it is inconvenient, and if you have to mix variadic args from multiple functions you have to copy them to a single table, and then unpack them.&lt;/p&gt;
&lt;p&gt;Sorry for this long tangent, but when I was thinking about how I would implement multiple values in Lox.
I&amp;rsquo;m OK with the syntax of Lua here, e.g. &lt;code&gt;return a, b, c&lt;/code&gt; and &lt;code&gt;local a, b, c = foo()&lt;/code&gt;.
However, this was hard to do properly.&lt;/p&gt;
&lt;p&gt;I had to change how the return statement works.
It&amp;rsquo;s not hard, we can read values until we find the &lt;code&gt;;&lt;/code&gt; token.
We also count the values, and emit the count with the instruction:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; returnStatement(self: *Parser) LoxError!&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.match(.SEMICOLON)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitReturn();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; valueCount: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; do = &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// do-while when?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (do &lt;span style=&#34;font-weight:bold&#34;&gt;or&lt;/span&gt; self.match(.COMMA)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            do = &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (valueCount == 255)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                self.error_(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Can&amp;#39;t return more than 255 values.&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            valueCount += 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.SEMICOLON, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;;&amp;#39; after return value.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.emitBytes(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Ret), &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(valueCount));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OK, we can emit the necessary code, but what do we do with it?&lt;/p&gt;
&lt;p&gt;One thing we can do is create a slice from the stack and return it as a single value.
Then, when we use it as a function parameter, or in an expression, we do the appropriate thing.
However, this isn&amp;rsquo;t particularly great, because the stack is mutable, and we manipulate it extensibly.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; var x = (\-&amp;gt; return 1, 2, 3)();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; print(x)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1 2 3
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; return x + 10;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;20
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Oops, we&amp;rsquo;ve pushed to the beginning of the stack, and x became &lt;code&gt;10&lt;/code&gt;.
Well, perhaps we can keep the stack slice, and just not decrement it, but we need to decide when to decrement it, i.e. once multiple values are no longer used.
Which is hard to track.&lt;/p&gt;
&lt;p&gt;The reason I wanted to be able to store multiple values in a single variable is because I want them to behave more like tuples, but that are always on the stack, no matter what.
So they remain fast, without additional memory allocations.
And to be able to make a closure over the multiple values, so we don&amp;rsquo;t have to fiddle with them like in Lua.
This, however, had problems all over the place.&lt;/p&gt;
&lt;p&gt;I also needed to implement a syntax for assigning multiple values to multiple variables, but I felt that at this point I was kinda burned out with the project.
I&amp;rsquo;m satisfied with the data structures that I added, and other stuff that is not available in the book.
All in all, I feel that I had a good grasp of what this book tried to cover.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Thoughts on Crafting Interpreters - Part 3&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Thu, 25 Jan 2024 23:23:00 +0300</pubDate>
    </item><item>
      <title>Thoughts on Crafting Interpreters - Part 2</title>
      <link>https://andreyor.st/posts/2024-01-15-thoughts-on-crafting-interpreters-part-2/</link>
      <guid>https://andreyor.st/posts/2024-01-15-thoughts-on-crafting-interpreters-part-2/</guid>
      <description>&lt;p&gt;This is a second post about the &lt;a href=&#34;http://craftinginterpreters.com/&#34; target=&#34;_blank&#34;&gt;Crafting Interpreters&lt;/a&gt; book by Robert Nystrom.&lt;/p&gt;
&lt;p&gt;In the first post, I&amp;rsquo;ve described my experience with the first half of the book, and the challenges of using a different language with different idioms and practices.
This post will be no different, although I have a bit more to discuss, and the contents aren&amp;rsquo;t actually ~2-year-old weak impressions and remembrances.
That being said, this is a second iteration both on this post and on the book so a lot of frustration I had with the book the first time I went through is coming from memory.
Well, these memories aren&amp;rsquo;t as old, as I did the project more recently, but still, I&amp;rsquo;ll point out when the complaints come from the old version or the new one.&lt;/p&gt;
&lt;p&gt;Same as before, I decided to choose a different implementation language, rather than using the one suggested by the author.
Please note, that this decision isn&amp;rsquo;t done for the sake of just using a different language - I have pretty practical reasons to do that.
Even more so than in the first half of the book.&lt;/p&gt;
&lt;p&gt;For the bytecode VM, Robert chooses the C programming language.
It is again, a reasonable choice, and I agree, that for a book on a language runtime, there are probably no other valid choices.
For a &lt;strong&gt;book&lt;/strong&gt;, that is.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not writing a book, however, so I felt that C is a rather poor choice for an actual implementation.
Not that I&amp;rsquo;m suggesting that C is a bad language for this kind of task - it has several advantages over most others, but in general, C isn&amp;rsquo;t the best pick today.
C demands &lt;strong&gt;a lot&lt;/strong&gt; of knowledge of how computers work, and it is the least forgiving language when it comes to fixing bugs down the line.
We&amp;rsquo;ve been writing C since the 1970s and haven&amp;rsquo;t perfected it by any means.
Memory errors are everywhere, programs segfault, and a lot of projects dedicated to finding errors in C code are basically required for any modern work done in C because humans are, in fact, humans.&lt;/p&gt;
&lt;p&gt;If someone claims that they &lt;em&gt;know C&lt;/em&gt;, they are either lying or are extremely rare cases of people who actually know what they&amp;rsquo;re doing.
I don&amp;rsquo;t think I have ever publicly said that I &lt;em&gt;know&lt;/em&gt; C, but I did work with C professionally in the bare metal context, and it&amp;rsquo;s a whole different story to working with C in the context of the operating system.
So even there we can&amp;rsquo;t say that we really know C if we only use it in one of the many possible contexts where you can use C.
Well, at least I worked with ASM as well, so when I saw the C code I could roughly see what ASM would correspond to it.&lt;/p&gt;
&lt;p&gt;Yes, C is still good for teaching the concepts behind data structures, used for language implementation, as you do have to implement them for yourself a lot.
The context that C is used in often requires this, because libraries might not be available for your specific use case.
So implementing stuff in C, especially given that this language just steps aside and says: &amp;ldquo;go&amp;rdquo;, not holding your hand, not preventing you from doing crazy shit like many modern languages often do.
&lt;em&gt;Oh, so you want to create an array, fill it with random numbers, cast it to the function, and run your machine code you&amp;rsquo;ve just put in - be my guest, that&amp;rsquo;s what we call meta-programming!&lt;/em&gt;
As ridiculous as it is, I have done that in the past.&lt;/p&gt;
&lt;p&gt;But, I don&amp;rsquo;t want to write in C anymore for many reasons.
So, what language did I pick?&lt;/p&gt;
&lt;p&gt;Well, since you have seen the tags for this post, you already know that it is the Zig programming language.
However, I have considered a number of other languages.
Namely Nim, Hare, Zig, Ada, and even OCaml.&lt;/p&gt;
&lt;p&gt;I have already tried Rust for this kind of project before, so I knew that I didn&amp;rsquo;t want to do it again with the same language.
I realized that I don&amp;rsquo;t like Rust in general.
The idea is nice on paper, but I believe it&amp;rsquo;s overly fixated.
And I have my thoughts on the Rust community, so this language isn&amp;rsquo;t really for me.&lt;/p&gt;
&lt;p&gt;But I wanted a language that can be considered a system language, much like C is.
And while Rust is indeed used for Linux kernel, I, myself, can&amp;rsquo;t consider it a system programming language, much like I can&amp;rsquo;t consider C++ to be one, even though you can write a system in it, for example &lt;a href=&#34;https://www.haiku-os.org&#34; target=&#34;_blank&#34;&gt;Haiku&lt;/a&gt;.
You can write systems in all kinds of languages, but I think that a system programming language has to have some pretty specific features and these are usually related to the ability to understand code, not to write one.
Rust and many others failed this for me.&lt;/p&gt;
&lt;p&gt;So, I quickly decided that I didn&amp;rsquo;t want to use &lt;a href=&#34;https://nim-lang.org/&#34; target=&#34;_blank&#34;&gt;Nim&lt;/a&gt; because of its Python-like syntax which I don&amp;rsquo;t like at all.
It may be a decent language, but the other point I don&amp;rsquo;t like about it in comparison to the other is that it is transpiled to C and then compiled, correct me if I&amp;rsquo;m wrong and things have changed since when it was like that.
I don&amp;rsquo;t think that this approach is bad, but I think that C is a poor target to compile to, and I can&amp;rsquo;t be sure that everything I write clearly translates to C without weird shenanigans that can have weird or unexpected behavior.
Although more languages do that, namely ECL and Gambit Scheme, it&amp;rsquo;s not impossible to do this well.
Sadly I think Scheme is a better language than Nim.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://ocaml.org/&#34; target=&#34;_blank&#34;&gt;OCaml&lt;/a&gt; is often brought up when discussing a language for writing compilers.
There are valid reasons to use it, but I&amp;rsquo;m quite unfamiliar with the ML family of languages, so I decided to not use it.
Also, OCaml is often used for its ability to work with LLVM, which isn&amp;rsquo;t what we&amp;rsquo;re doing in the book.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://harelang.org/&#34; target=&#34;_blank&#34;&gt;Hare&lt;/a&gt; is a relatively new language by Drew DeVault.
From what I&amp;rsquo;ve seen about this language it seems interesting, and it has a nice article &lt;a href=&#34;https://harelang.org/blog/2021-02-09-hare-advances-on-c/&#34; target=&#34;_blank&#34;&gt;listing the advantages over C&lt;/a&gt;.
However, the documentation was almost non-existent at the moment I started this project, and I didn&amp;rsquo;t want to dive into a language that was in so early stages of its development.
I have vague plans on maybe doing a Forth implementation in Hare in the future, so I&amp;rsquo;ll get to try it eventually.
I would say that Hare was a close second to me.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://www.adaic.org/&#34; target=&#34;_blank&#34;&gt;Ada&lt;/a&gt; seems like an interesting language, and I have read the &lt;em&gt;hellscape&lt;/em&gt; of a code from one of the projects done by a member of a community in which I hang out.
While it seems like a capable language, I didn&amp;rsquo;t like it that much to try it myself.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s also &lt;a href=&#34;https://odin-lang.org/&#34; target=&#34;_blank&#34;&gt;Odin&lt;/a&gt;&amp;hellip; I have never heard of this language and it&amp;rsquo;s being used anywhere, but according to their web page, it&amp;rsquo;s basically everywhere.
That seems like a stretch for a project that started in 2016.
Zig started in 2015 and had no stable release yet, and Odin claims to be professionally used in so many game studios and other companies, and yet I haven&amp;rsquo;t heard of it at all!
I consider myself a language enthusiast, yet somehow this language completely dodged my field of view.
Maybe they&amp;rsquo;re that good, I don&amp;rsquo;t know, but I decided that I&amp;rsquo;ll pass.&lt;/p&gt;
&lt;p&gt;Jai, a language by Jonathan Blow, also seemed interesting to try out, but I feel that its aim at being a replacement for C++ in the game programming field is not exactly what I&amp;rsquo;m looking for.
At the time of writing, it&amp;rsquo;s still in a closed beta test, so it&amp;rsquo;s hard to get hands on it, and judging from what I have seen in the videos, it&amp;rsquo;s not like I would use this language for this particular project either.&lt;/p&gt;
&lt;p&gt;Before you ask, I haven&amp;rsquo;t considered Go for this project, because I simply don&amp;rsquo;t like Go.
There&amp;rsquo;s the &lt;a href=&#34;https://interpreterbook.com&#34; target=&#34;_blank&#34;&gt;interpreterbook&lt;/a&gt; book which is oddly similarly named to the book discussed in this post, and it is written in Go, so you don&amp;rsquo;t even have to go through translating C to Go if you want to learn how to design a language if Go is your thing.
Well, I have my reasons to dislike Go, but I don&amp;rsquo;t want to go into them here.
Maybe next time.&lt;/p&gt;
&lt;p&gt;And yes, there are many more languages that can be used for this kind of task - obviously, I can&amp;rsquo;t compare all of them.
So I had to stop somewhere.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&#34;https://ziglang.org/&#34; target=&#34;_blank&#34;&gt;Zig&lt;/a&gt; programming language caught my eye a few years ago after it was pointed out to me as a response to my &lt;a href=&#34;https://andreyor.st/posts/2020-04-06-c-needs-a-better-syntax/&#34;&gt;rant&lt;/a&gt; about C.
It is more mature than Hare, and as far as I know, the 1.0.0 release is not as far away.
And for what it&amp;rsquo;s worth, it is closest to C in many ways that Ada or Rust are not.
So I decided that it would be a proper pick for the second half of the book.&lt;/p&gt;
&lt;h2 id=&#34;zig&#34;&gt;Zig&lt;/h2&gt;
&lt;p&gt;So I chose Zig.
At the moment of writing this post, the latest release is 0.11.0, which is important to note as Zig is still constantly changing.
While this is a good thing, and I understand that Zig had no stable release yet, I am spoiled.
I am spoiled by languages with the stable core, like Clojure, where you can find a 13-year-old code and run it with the modern version of Clojure.
That&amp;rsquo;s not how it works with Zig.
A lot of code I&amp;rsquo;ve tried during this experiment did not work because it was written for an older version of Zig.&lt;/p&gt;
&lt;p&gt;As you may remember from part 1 - this is a second try on writing the second half of the book in Zig.
The first try wasn&amp;rsquo;t successful, and I&amp;rsquo;m going to discuss this separately later in this post.
During the first iteration, I had to learn many things about the language and its build system.
After I hit the point where my implementation did not work (for reasons described later), I decided to delete everything and start over (for reasons described later).&lt;/p&gt;
&lt;p&gt;So I took a considerable amount of time to rest from this project and in the meantime, Zig 0.11.0 was released.
This is important because the previous run was done using Zig 0.10.0, and I deleted everything, &lt;strong&gt;except&lt;/strong&gt; for the &lt;code&gt;build.zig&lt;/code&gt; that I had spent a lot of time creating to fulfill my needs.
And now it doesn&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;That made me realize that I didn&amp;rsquo;t actually spend any time in the previous post talking about the build system.
So let&amp;rsquo;s do that right now!&lt;/p&gt;
&lt;h3 id=&#34;clojure-build-system&#34;&gt;Clojure build system&lt;/h3&gt;
&lt;p&gt;So, in the Clojure version of the Lox language, I opted to use the &lt;code&gt;deps.edn&lt;/code&gt; which is pretty much the standard way to create projects in Clojure.
There are other systems that can help manage projects, notably Leiningen, but I like to do things manually, for better understanding, so when I can I use stuff like deps.
And unlike Leiningen, deps doesn&amp;rsquo;t come with the automatic building of your project - you have to make it by yourself.&lt;/p&gt;
&lt;p&gt;And that&amp;rsquo;s actually great!
I like the idea that builds are programs because you can write custom builds that are specific to your project&amp;rsquo;s needs.
Of course, most projects don&amp;rsquo;t need anything fancy, so there is a library that provides the basic stuff you&amp;rsquo;ll probably need.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what the &lt;code&gt;build.clj&lt;/code&gt; looks like for CljLox:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;build&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clojure.tools.build.api&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lib&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;lox&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;version&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;0.0.%s&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b/git-count-revs&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;class-dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;target/clojure/classes&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;basis&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b/create-basis&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:project&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;deps.edn&amp;#34;&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uber-file&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;target/clojure/%s-%s-standalone.jar&amp;#34;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lib&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;version&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clean&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b/delete&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:path&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;target/clojure&amp;#34;&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uber&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clean&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b/copy-dir&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:src-dirs&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:target-dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;class-dir&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b/compile-clj&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:basis&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;basis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:src-dirs&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;src&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:class-dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;class-dir&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b/uber&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:class-dir&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;class-dir&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:uber-file&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;uber-file&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:basis&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;basis&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:main&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;lox.core&lt;/span&gt;}))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it!&lt;/p&gt;
&lt;p&gt;I like the idea of using the number of commits since the repository creation as the last component of the version, and the build library provides a function for that: &lt;code&gt;b/git-count-revs&lt;/code&gt;.
We do have to specify some paths, create a basis, whatever it is, and just define the compilation functions.
We then execute it like &lt;code&gt;clojure -T:build uber&lt;/code&gt;, and it creates the &lt;code&gt;lox-0.0.123-standalone.jar&lt;/code&gt; file that we can later run with the &lt;code&gt;java -jar&lt;/code&gt; command.&lt;/p&gt;
&lt;p&gt;Simple and effective.
If my project required additional steps I could just define more functions to do these steps.
Let&amp;rsquo;s compare that to Zig, shall we?&lt;/p&gt;
&lt;h3 id=&#34;zig-build&#34;&gt;Zig build&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s the entire &lt;code&gt;build.zig&lt;/code&gt; for the previous version of ZigLox:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; std = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;std&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Version = std.builtin.Version;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Builder = std.build.Builder;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; print = std.debug.print;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; LibExeObjStep = std.build.LibExeObjStep;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Mode = std.builtin.Mode;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; CrossTarget = std.zig.CrossTarget;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Step = std.build.Step;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; trimRight = std.mem.trimRight;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; parseInt = std.fmt.parseInt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; exit = std.process.exit;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; fs = std.fs;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; MAJOR = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; MINOR = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; gitCountRevs(b: *Builder) &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; code: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt; = &lt;span style=&#34;font-weight:bold&#34;&gt;undefined&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    b: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; commits_num = trimRight(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            b.execAllowFail(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &amp;amp;[_][]&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;{ &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;git&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-C&amp;#34;&lt;/span&gt;, b.build_root, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;rev-list&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;HEAD&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;--count&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &amp;amp;code,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Ignore,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt; :b,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; parseInt(&lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;, commits_num, 10) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt; :b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;unable to count number of revs&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exit(1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; getVersion(b: *Builder) Version {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Version{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .major = MAJOR,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .minor = MINOR,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .patch = gitCountRevs(b),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isZigFile(name: []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; std.mem.eql(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, name[name.len - 4 ..], &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.zig&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// Automatically resolves packages under the source directory.  Adds
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// packages to the `exe`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; resolveAndAddPackages(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    src_dir: []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    allocator: std.mem.Allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exe: *LibExeObjStep,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; dir = std.fs.cwd().openIterableDir(src_dir, .{}) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; exit(2);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; iterator = dir.iterate();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (iterator.next() &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;) |path| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (isZigFile(path.name)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; package_name = path.name[0 .. path.name.len - 4];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; src_path = fs.path.join(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &amp;amp;[_][]&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;{ src_dir, path.name },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; exit(3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            exe.addPackagePath(package_name, src_path);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// Automatically finds tests under the test directory, adds the test
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// to the build `step`, and adds all necessary packages for test to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// run.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; resolveAndAddTests(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    b: *Builder,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    test_dir: []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    allocator: std.mem.Allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    mode: Mode,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    target: CrossTarget,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    step: *Step,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; dir = std.fs.cwd().openIterableDir(test_dir, .{}) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; exit(2);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; iterator = dir.iterate();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (iterator.next() &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;) |path| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (isZigFile(path.name)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; test_path = fs.path.join(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &amp;amp;[_][]&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;{ test_dir, path.name },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; exit(3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; tests = b.addTest(test_path);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            resolveAndAddPackages(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;src/zig/lox&amp;#34;&lt;/span&gt;, allocator, tests);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tests.setTarget(target);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            tests.setBuildMode(mode);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            step.dependOn(&amp;amp;tests.step);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; build(b: *Builder) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;defer&lt;/span&gt; arena.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; allocator = arena.allocator();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; version = getVersion(b);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; version_string = b.fmt(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{[major]d}.{[minor]d}.{[patch]d}&amp;#34;&lt;/span&gt;, version);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; target = b.standardTargetOptions(.{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; mode = b.standardReleaseOptions();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; exe = b.addExecutable(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b.fmt(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;lox-{s}&amp;#34;&lt;/span&gt;, .{version_string}),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;src/zig/lox/main.zig&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exe.setTarget(target);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exe.setBuildMode(mode);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    exe.install();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; run_cmd = exe.run();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    run_cmd.step.dependOn(b.getInstallStep());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (b.args) |args| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        run_cmd.addArgs(args);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; run_step = b.step(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;run&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Run the app&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    run_step.dependOn(&amp;amp;run_cmd.step);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; test_step = b.step(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;test&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Run unit tests&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; test_dir = fs.path.join(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;amp;[_][]&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;{ &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;test&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;zig&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;lox&amp;#34;&lt;/span&gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; exit(1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    resolveAndAddTests(b, test_dir, allocator, mode, target, test_step);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s not that big, but the amount of boilerplate you have to do, even though the language has a build library is far greater than in Clojure.
I do understand that these things pursue different goals, but does it really need to be that complicated?&lt;/p&gt;
&lt;p&gt;Actually, let me explain why it is so complicated.
You see, I have a quite specific project layout in mind:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Lox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── build.clj
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── build.zig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── deps.edn
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── src
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── clojure
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │   └── lox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   │       └── sources.clj
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── zig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│       └── lox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│           └── sources.zig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;├── target
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   ├── clojure
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;│   └── zig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;└── test
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── clojure
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── lox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │       └── test_sources.clj
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ├── data
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    │   └── various_test_files
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    └── zig
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        └── lox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            └── test_sources.zig
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So the sources are located in the &lt;code&gt;src&lt;/code&gt; directory, and the tests are located in the &lt;code&gt;test&lt;/code&gt; directory.
And each implementation has a language directory in there, so Clojure sources are in the &lt;code&gt;src/clojure&lt;/code&gt; and the Zig sources are in &lt;code&gt;src/zig&lt;/code&gt;.
The same goes for tests.&lt;/p&gt;
&lt;p&gt;Unfortunately, I couldn&amp;rsquo;t find a way to have tests outside of the source directory, so I had to dance around, creating my own solution for this self-introduced problem.
Is it that uncommon to put tests into a separate directory, outside of the source directory?
Let&amp;rsquo;s look at other languages.&lt;/p&gt;
&lt;p&gt;In Java, this is the norm, same in Clojure.
I like this actually, tests are separate entities, they don&amp;rsquo;t have anything to do with the source code.
I mean, the source is for the actual application or the library you ship to the consumer.
The tests are for you, the developer, not for the consumer.&lt;/p&gt;
&lt;p&gt;In Rust, the tests usually are in the same file as the source code.
When I was writing in Rust I kinda liked it, but only, seriously, &lt;strong&gt;only&lt;/strong&gt; because before Rust I was writing C professionally, and tests in C are, well, they&amp;rsquo;re not standardized, to say the least.
So having Rust giving you tools to write and run tests was a huge step up from C, but that was the only step up.&lt;/p&gt;
&lt;p&gt;In Go it is possible to put tests in a different directory, and I&amp;rsquo;ve seen projects doing it, so I guess that&amp;rsquo;s a fine part of Go.&lt;/p&gt;
&lt;p&gt;What else can we look at? Nim? Seems that putting tests into a separate directory is possible there.
Hare? From what I can see, the projects have either &lt;code&gt;+test.ha&lt;/code&gt; or just &lt;code&gt;test.ha&lt;/code&gt; files in the same place where the sources are - not sure if this is the only way it can work, the hare docs are sparse on the details here.&lt;/p&gt;
&lt;p&gt;Well, I guess there&amp;rsquo;s no single answer to this question, but I don&amp;rsquo;t see why a language would forbid putting tests whenever the project author sees fit.
And in Zig, well, while it was hard to make it, and make it fully automatic, remember - the build is a program.
You can do whatever you want, as long as the tooling gives you the ability, and in the case of Zig, the build system can do that.
Well, at least it could in 0.10.0, but now I have to rewrite it for 0.11.0.&lt;/p&gt;
&lt;p&gt;I had a few hiccups and managed to do that, so I&amp;rsquo;m not going to complain that much here, but I still think it&amp;rsquo;s too complicated.
I mean, it&amp;rsquo;s not as complicated as it was in 0.10.0, so that&amp;rsquo;s good, but it is still a lot of manual work.
Here&amp;rsquo;s a diff with the previous version so you can feel the amount of subtle changes I had to make to make this thing compile again:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -1,11 +1,10 @@
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const std = @import(&#34;std&#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-const Version = std.builtin.Version;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-const Builder = std.build.Builder;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+const Builder = std.Build;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+const Step = Builder.Step;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const print = std.debug.print;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-const LibExeObjStep = std.build.LibExeObjStep;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+const CompStep = Step.Compile;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const Mode = std.builtin.Mode;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const CrossTarget = std.zig.CrossTarget;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-const Step = std.build.Step;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const trimRight = std.mem.trimRight;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const parseInt = std.fmt.parseInt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const exit = std.process.exit;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -14,6 +13,12 @@ const fs = std.fs;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const MAJOR = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; const MINOR = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+const Version = struct {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    major: u32,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    minor: u32,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    commits: u32,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; fn gitCountRevs(b: *Builder) u32 {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     var code: u8 = undefined;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     b: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -46,10 +51,10 @@ fn isZigFile(name: []const u8) bool {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; /// Automatically resolves packages under the source directory.  Adds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; /// packages to the `exe`.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-fn resolveAndAddPackages(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+fn resolveAndAddModules(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    b: *Builder,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     src_dir: []const u8,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    allocator: std.mem.Allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    exe: *LibExeObjStep,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    exe: *CompStep,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ) void {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     const dir = std.fs.cwd().openIterableDir(src_dir, .{}) catch exit(2);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     var iterator = dir.iterate();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -57,11 +62,8 @@ fn resolveAndAddPackages(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     while (iterator.next() catch null) |path| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         if (isZigFile(path.name)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             const package_name = path.name[0 .. path.name.len - 4];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            const src_path = fs.path.join(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-                allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-                &amp;amp;[_][]const u8{ src_dir, path.name },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            ) catch exit(3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            exe.addPackagePath(package_name, src_path);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+            const src_path = b.pathJoin(&amp;amp;.{ src_dir, path.name });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+            exe.addModule(package_name, b.createModule(.{ .source_file = .{ .path = src_path } }));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -71,9 +73,9 @@ fn resolveAndAddPackages(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; /// run.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; fn resolveAndAddTests(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     b: *Builder,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    src_dir: []const u8,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     test_dir: []const u8,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    allocator: std.mem.Allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    mode: Mode,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    optimize: Mode,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     target: CrossTarget,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     step: *Step,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; ) void {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;@@ -82,52 +84,41 @@ fn resolveAndAddTests(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     while (iterator.next() catch null) |path| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         if (isZigFile(path.name)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            const test_path = fs.path.join(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-                allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-                &amp;amp;[_][]const u8{ test_dir, path.name },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            ) catch exit(3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            const tests = b.addTest(test_path);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            resolveAndAddPackages(&#34;src/zig/lox&#34;, allocator, tests);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            tests.setTarget(target);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            tests.setBuildMode(mode);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-            step.dependOn(&amp;amp;tests.step);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+            const tests = b.addTest(.{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+                .name = path.name,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+                .root_source_file = .{ .path = b.pathJoin(&amp;amp;.{ test_dir, path.name }) },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+                .target = target,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+                .optimize = optimize,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+            });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+            resolveAndAddModules(b, src_dir, tests);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+            step.dependOn(&amp;amp;b.addRunArtifact(tests).step);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; pub fn build(b: *Builder) void {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    defer arena.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    const allocator = arena.allocator();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    const version = getVersion(b);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    const version_string = b.fmt(&#34;{[major]d}.{[minor]d}.{[patch]d}&#34;, version);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    const version = b.fmt(&#34;{[major]d}.{[minor]d}.{[commits]d}&#34;, getVersion(b));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     const target = b.standardTargetOptions(.{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    const mode = b.standardReleaseOptions();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    const exe = b.addExecutable(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-        b.fmt(&#34;lox-{s}&#34;, .{version_string}),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-        &#34;src/zig/lox/main.zig&#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    );
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    exe.setTarget(target);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    exe.setBuildMode(mode);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    exe.install();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    const run_cmd = exe.run();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    run_cmd.step.dependOn(b.getInstallStep());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    if (b.args) |args| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-        run_cmd.addArgs(args);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    const optimize = b.standardOptimizeOption(.{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    const src_dir = b.pathJoin(&amp;amp;.{ &#34;src&#34;, &#34;zig&#34;, &#34;lox&#34; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    const main = b.pathJoin(&amp;amp;.{ src_dir, &#34;main.zig&#34; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    const exe = b.addExecutable(.{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+        .name = b.fmt(&#34;lox-{s}&#34;, .{version}),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+        .root_source_file = .{ .path = main },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+        .target = target,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+        .optimize = optimize,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    b.installArtifact(exe);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    const run_cmd = b.addRunArtifact(exe);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     const run_step = b.step(&#34;run&#34;, &#34;Run the app&#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     run_step.dependOn(&amp;amp;run_cmd.step);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     const test_step = b.step(&#34;test&#34;, &#34;Run unit tests&#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    const test_dir = fs.path.join(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-        allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-        &amp;amp;[_][]const u8{ &#34;test&#34;, &#34;zig&#34;, &#34;lox&#34; },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    ) catch exit(1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    const test_dir = b.pathJoin(&amp;amp;.{ &#34;test&#34;, &#34;zig&#34;, &#34;lox&#34; });
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-    resolveAndAddTests(b, test_dir, allocator, mode, target, test_step);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+    resolveAndAddTests(b, src_dir, test_dir, optimize, target, test_step);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Yet, this isn&amp;rsquo;t a final version of the file&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;, just the first working one.
Gotta say, I had to spend a few hours figuring out why tests don&amp;rsquo;t actually run, only to notice a line in the changelog:&lt;/p&gt;
&lt;blockquote&gt;
&lt;h2&gt;addTest No Longer Runs It&lt;/h2&gt;
&lt;p&gt;Before, addTest created and ran a test. Now you need to use b.addRunArtifact to run your test executable.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;That&amp;rsquo;s on me, of course, cuz I haven&amp;rsquo;t taken my time to read the whole changelog.
But it&amp;rsquo;s like 24k words without the code, so can you blame me?
I just had a stroke of passion to restart this project, and I didn&amp;rsquo;t really want to kill it by reading a huge changelog of the language I already don&amp;rsquo;t remember almost completely.
So for me, it is not even a &lt;em&gt;change&lt;/em&gt; log, it&amp;rsquo;s just a log.&lt;/p&gt;
&lt;p&gt;But it now works and that&amp;rsquo;s the only thing that matters.
Hopefully, I&amp;rsquo;ll finish this project before 0.12.0 comes out, and I&amp;rsquo;ll reimplement everything &lt;em&gt;again&lt;/em&gt;.
Oh well, I can just not update, but the language is being improved so I&amp;rsquo;d rather not miss on these improvements.&lt;/p&gt;
&lt;p&gt;With that covered, I think we can actually start with the book!&lt;/p&gt;
&lt;h2 id=&#34;chunks-of-bytecode&#34;&gt;Chunks of Bytecode&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s going to be an ongoing theme with this book: I&amp;rsquo;m not going to re-implement low-level machinery for the sake of implementing it.
It&amp;rsquo;s something I need to say early on, as the book is full of this, and while I understand the author&amp;rsquo;s intent, I&amp;rsquo;m not the type of reader the book really aims for.&lt;/p&gt;
&lt;p&gt;What I&amp;rsquo;m talking about is implementing such things as dynamic arrays.
Zig already comes with the dynamic array, called the &lt;code&gt;ArrayList&lt;/code&gt;.
If you&amp;rsquo;re curious enough, you can check how it is implemented, and it is almost exactly the same as what is described in the book.
I implemented it during the first run, looked at it, looked at the standard library implementation, said to myself &amp;ldquo;I got it&amp;rdquo;, and decided not to reinvent the wheel.
These tricks, while neat, are only meaningful to C - in Zig, we can and should use the standard library.&lt;/p&gt;
&lt;p&gt;Even if we don&amp;rsquo;t re-implement all this stuff, there are a lot of differences in implementing things with Zig.
Let&amp;rsquo;s have a look at the code for the chunk:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; std = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;std&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; ArrayList = std.ArrayList;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; common = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;common.zig&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Code = common.Code;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; OPCode = common.OPCode;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Allocator = common.Allocator;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; exit = common.exit;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; print = common.print;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; str = common.str;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Chunk = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Self = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@This&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    code: ArrayList(Code),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; init(allocator: Allocator) Chunk {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Chunk{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .code = ArrayList(Code).init(allocator),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; deinit(self: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.code.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; write(self: *Self, byte: OPCode) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.code.append(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(byte)) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            exit(1, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;can&amp;#39;t allocate memory for the instruction&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; simpleInstruction(name: str, offset: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        std.debug.print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{s: &amp;lt;16}&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;, .{name});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; offset + 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; disassembleInstruction(self: *Self, offset: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{d:0&amp;gt;4} &amp;#34;&lt;/span&gt;, .{offset});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; opcode = self.code.items[offset];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(OPCode, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@enumFromInt&lt;/span&gt;(opcode))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .Ret =&amp;gt; |op| simpleInstruction(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@tagName&lt;/span&gt;(op), offset),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; |op| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;unknown opcode {d}&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;, .{op});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; offset + 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; disassemble(self: *Self, name: str) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;==== {s} ====&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;, .{name});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; offset: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (offset &amp;lt; self.code.items.len) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            offset = self.disassembleInstruction(offset);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 1:&lt;/span&gt;
  src/zig/lox/chunk.zig
&lt;/div&gt;
&lt;p&gt;Do you see that barrage of &lt;code&gt;const&lt;/code&gt; definitions at the top?
There will be lots of these things during this post.
As you can actually notice, a dozen came from the &lt;code&gt;common.zig&lt;/code&gt; module:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; std = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;std&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Allocator = std.mem.Allocator;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; str = []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Code = &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; print = std.debug.print;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; OPCode = &lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;(Code) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Ret,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; exit(code: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, msg: str) &lt;span style=&#34;font-weight:bold&#34;&gt;noreturn&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{s}&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;, .{msg});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    std.process.exit(code);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 2:&lt;/span&gt;
  src/zig/lox/common.zig
&lt;/div&gt;
&lt;p&gt;Zig claims that the top-level constants don&amp;rsquo;t have to be ordered, which while convenient, I don&amp;rsquo;t think is practically good.
I do prefer a top-down approach, where the most specific things appear at the top, and more general stuff is at the bottom.
So if this isn&amp;rsquo;t your cup of tea, well, sorry, I guess?&lt;/p&gt;
&lt;p&gt;Anyhow, here&amp;rsquo;s the &lt;code&gt;main.zig&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; std = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;std&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Chunk = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;chunk.zig&amp;#34;&lt;/span&gt;).Chunk;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; common = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;common.zig&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; OPCode = common.OPCode;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; main() !&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;defer&lt;/span&gt; arena.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; allocator = arena.allocator();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; chunk = Chunk.init(allocator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;defer&lt;/span&gt; chunk.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk.write(OPCode.Ret);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk.disassemble(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;test chunk&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 3:&lt;/span&gt;
  src/zig/lox/main.zig
&lt;/div&gt;
&lt;p&gt;If we run it with &lt;code&gt;zig build run&lt;/code&gt;, we get a lovely:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ zig build run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;==== test chunk ====
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;0000 Ret
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So far so good.
Note, this is code up to the part where we are supposed to add a value array for constants, so it&amp;rsquo;s not like it&amp;rsquo;s the whole code for the chapter.
For now, I won&amp;rsquo;t go into code explanations, it&amp;rsquo;s not that hard right now, you can get the idea just by reading it, and by referring to the book.
But there is a reason why I decided to show it right now.&lt;/p&gt;
&lt;h3 id=&#34;adding-constants&#34;&gt;Adding constants&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at how the book suggests to add the constants.&lt;/p&gt;
&lt;p&gt;First, we introduce the &lt;code&gt;addConstant&lt;/code&gt; function, which adds a &lt;code&gt;Value&lt;/code&gt; type to the dynamic array of constants.
Next, we use &lt;code&gt;writeChunk&lt;/code&gt;, or in my case &lt;code&gt;chunk.write&lt;/code&gt; to write the constant index in the array to the &lt;code&gt;code&lt;/code&gt; array of the chunk.
Do you see the issue here?
Let&amp;rsquo;s look at the code then.&lt;/p&gt;
&lt;p&gt;The first thing we do is add a new function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; addConstant(self: *Self, value: Value) Code {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self.constants.append(value) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        exit(1, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;can&amp;#39;t allocate memory for the constant&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@truncate&lt;/span&gt;(self.constants.items.len - 1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You may wonder, why am I using &lt;code&gt;@truncate&lt;/code&gt; on the return value, and the return type is &lt;code&gt;Code&lt;/code&gt;?
Especially since the code in the book tells us that it should return an &lt;code&gt;int&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;addConstant&lt;/span&gt;(Chunk* chunk, Value value) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  writeValueArray(&amp;amp;chunk-&amp;gt;constants, value);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; chunk-&amp;gt;constants.count - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, remember, our &lt;code&gt;write&lt;/code&gt; function (&lt;code&gt;writeChunk&lt;/code&gt; in the book) accepts the chunk and an opcode to write.
Initially, I&amp;rsquo;ve made it so that the signature expects the &lt;code&gt;OPCode&lt;/code&gt; enum itself:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; write(self: *Self, byte: OPCode) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.code.append(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(byte)) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            exit(1, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;can&amp;#39;t allocate memory for the instruction&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, that would mean, that if we were to pass the result of &lt;code&gt;addConstant&lt;/code&gt; to it, we would need to convert it to the enum tag, and then immediately convert it back to the &lt;code&gt;Code&lt;/code&gt; type, that the &lt;code&gt;ArrayList&lt;/code&gt; uses to store code in the chunk.
So, I&amp;rsquo;ve changed it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; write(self: *Self, byte: Code) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.code.append(byte) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            exit(1, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;can&amp;#39;t allocate memory for the instruction&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, we can add constants in the &lt;code&gt;main&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; main() !&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;defer&lt;/span&gt; arena.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; allocator = arena.allocator();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; chunk = Chunk.init(allocator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;defer&lt;/span&gt; chunk.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; constant = chunk.addConstant(1.2);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk.write(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Constant));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk.write(constant);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk.disassemble(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;test chunk&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Still don&amp;rsquo;t see the issue?
Well, &lt;code&gt;@truncate&lt;/code&gt; kinda spoiled it, so I&amp;rsquo;ll get straight to the point - we can only have 256 constants in the Chunk.
The rest will overflow our &lt;code&gt;Code&lt;/code&gt; type, which is, in fact, just a &lt;code&gt;u8&lt;/code&gt; in disguise.&lt;/p&gt;
&lt;p&gt;The book overlooks this for now, as in C truncation happens automatically, but comes back to it in the &amp;ldquo;Challenges&amp;rdquo; section.
And, as you may remember I&amp;rsquo;ve promised that I have a lot to say about the &amp;ldquo;Challenges&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the &amp;ldquo;Challenge&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Because &lt;code&gt;OP_CONSTANT&lt;/code&gt; uses only a single byte for its operand, a chunk may only contain up to 256 different constants.
That’s small enough that people writing real-world code will hit that limit.
We could use two or more bytes to store the operand, but that makes every constant instruction take up more space.
Most chunks won’t need that many unique constants, so that wastes space and sacrifices some locality in the common case to support the rare case.&lt;/p&gt;
&lt;p&gt;To balance those two competing aims, many instruction sets feature multiple instructions that perform the same operation but with operands of different sizes.
Leave our existing one-byte &lt;code&gt;OP_CONSTANT&lt;/code&gt; instruction alone, and define a second &lt;code&gt;OP_CONSTANT_LONG&lt;/code&gt; instruction.
It stores the operand as a 24-bit number, which should be plenty.&lt;/p&gt;
&lt;p&gt;Implement this function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;writeConstant&lt;/span&gt;(Chunk* chunk, Value value, &lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; line) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Implement me...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It adds &lt;code&gt;value&lt;/code&gt; to &lt;code&gt;chunk&lt;/code&gt;’s constant array and then writes an appropriate instruction to load the constant.
Also add support to the disassembler for &lt;code&gt;OP_CONSTANT_LONG&lt;/code&gt; instructions.&lt;/p&gt;
&lt;p&gt;Defining two instructions seems to be the best of both worlds.
What sacrifices, if any, does it force on us?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So here&amp;rsquo;s the problem - I had implemented this in the first run and regretted it many, many times.
So for this run, I&amp;rsquo;m not going to, sorry Robert.&lt;/p&gt;
&lt;p&gt;I mean, the challenge itself isn&amp;rsquo;t hard, however, the book assumes that you don&amp;rsquo;t do them because it is a &lt;em&gt;challenge&lt;/em&gt;, not homework that you &lt;em&gt;have&lt;/em&gt; to do.
So the latter chapters continue as if no challenges were even there - the code in the book still uses the naive truncated approach.&lt;/p&gt;
&lt;p&gt;I do understand that this book is about teaching how to implement a language and not a step-by-step guide.
But later, these challenges made my code so different from what the book gives you that I had several hours-long sessions of looking through the book, figuring out where the particular piece of code came from, and what the intention there was.
All because I had a bug &lt;em&gt;somewhere&lt;/em&gt; and the reason was usually that differences, introduced by the challenges, piled up and combined introducing a subtle bug that made itself visible only after several chapters.&lt;/p&gt;
&lt;p&gt;So, no challenges this time.
All I care about this time is to finish the book and have a working language written in Zig.&lt;/p&gt;
&lt;h3 id=&#34;line-information&#34;&gt;Line information&lt;/h3&gt;
&lt;p&gt;Sike!
Let&amp;rsquo;s do a challenge!&lt;/p&gt;
&lt;p&gt;The book suggests that we can store lines in a dynamic array, for each index of the chunk:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk-&amp;gt;lines[chunk-&amp;gt;count] = line;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, this is quite inefficient in terms of memory.
And the book mentions that in the &amp;ldquo;Challenges&amp;rdquo; section.
It suggests using a so-called &lt;a href=&#34;https://en.wikipedia.org/wiki/Run-length_encoding&#34; target=&#34;_blank&#34;&gt;Run-length encoding&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After scratching my head for a moment, I came up with this solution:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; writeLine(self: *Self, line: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; len = self.lines.items.len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (len &amp;gt; 1 &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.lines.items[len - 2] == line) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.lines.items[len - 1] = self.lines.items[len - 1] + 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.lines.append(line) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                exit(1, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;can&amp;#39;t allocate memory for line information&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.lines.append(1) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                exit(1, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;can&amp;#39;t allocate memory for line information&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 4:&lt;/span&gt;
  a method in the &lt;code&gt;Chunk&lt;/code&gt; struct
&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s a rather simple algorithm - we check if the last line is the same as the new one, and if it is, we increase the count, that is stored right next to it.
Otherwise, we append a new line and set its count to &lt;code&gt;1&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But now we need to extract line information by uncompressing this data:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; getLine(self: *&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Self, offset: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; cnt: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; off: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = offset;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (off &amp;gt; 0) loop: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; n: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = self.lines.items[cnt + 1];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (n &amp;gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (off == 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt; :loop;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                off = off - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                n = n - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            cnt = cnt + 2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.lines.items[cnt];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 5:&lt;/span&gt;
  a method in the &lt;code&gt;Chunk&lt;/code&gt; struct
&lt;/div&gt;
&lt;p&gt;Simply put, we&amp;rsquo;re decreasing the counter while the offset is greater than zero while increasing the counter each time we&amp;rsquo;ve exhausted the line counter &lt;code&gt;n&lt;/code&gt;.
Sure, it&amp;rsquo;s not a very fast algorithm, and we can probably do it without using loops if I think hard enough, but I&amp;rsquo;m OK with this solution.
It isn&amp;rsquo;t used until the chunk gets disassembled, and this only happens when we debug.&lt;/p&gt;
&lt;p&gt;This challenge I like.
It doesn&amp;rsquo;t affect the overall code of the VM and is more of a lesson in optimization.
We saved some memory, at the expense of a bit slower disassembler, which is fine by me.&lt;/p&gt;
&lt;p&gt;However, seriously, this is probably the last challenge I&amp;rsquo;ll tackle for a long time, so don&amp;rsquo;t get excited.&lt;/p&gt;
&lt;h3 id=&#34;tests&#34;&gt;Tests&lt;/h3&gt;
&lt;p&gt;As a final thing in this chapter, the book suggests testing your code.
And here&amp;rsquo;s the thing - it&amp;rsquo;s a great suggestion, only this book will make you hate your decision to test the code.
I&amp;rsquo;m a bit exaggerating here, but keep in mind, during this chapter we&amp;rsquo;ve already changed some parts of the &lt;code&gt;Chunk&lt;/code&gt; code several times.&lt;/p&gt;
&lt;p&gt;First, we introduced the &lt;code&gt;write&lt;/code&gt; method, and it accepted the &lt;code&gt;OPCode&lt;/code&gt; enum.
Next, we introduced the &lt;code&gt;addConstant&lt;/code&gt; method, and it required us to change the &lt;code&gt;write&lt;/code&gt; to accept the &lt;code&gt;Code&lt;/code&gt; instead.
Finally, we&amp;rsquo;ve added support for line information, changing the &lt;code&gt;write&lt;/code&gt; method once again.&lt;/p&gt;
&lt;p&gt;You may think that that&amp;rsquo;s fine, as we did it during one chapter, and the tests should be written after we complete it.
Well, &lt;abbr title=&#34;Tests Delay Deployment&#34;&gt;TDD&lt;/abbr&gt; people may disagree with you.
I&amp;rsquo;m not a TDD person, I usually test things as I go in the REPL, and then, once I&amp;rsquo;m satisfied I write proper tests to prevent later breakage.
But Zig doesn&amp;rsquo;t have a REPL, so testing it this way won&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;So, while Robert claims that: &amp;ldquo;I wrote a test suite for Lox before I wrote a single word of this book.&amp;rdquo;, I&amp;rsquo;d be cautious when writing tests for this book&amp;rsquo;s code.
Probably his claim is true, especially if he knew what the result would be and wrote a test for it.
Or, maybe the book was simply written after the implementation of the language became a thing, which then doesn&amp;rsquo;t matter if the tests were written upfront or not.&lt;/p&gt;
&lt;p&gt;I tend to write tests either during the chapter or at the end of it.
And at the first run, I did exactly that.
But, as we&amp;rsquo;ll see later, you&amp;rsquo;ll have to discard or rework &lt;strong&gt;a lot&lt;/strong&gt; of tests due to changes in the code.
And often the changes are dramatic, so I&amp;rsquo;m not sure if it makes sense to write too many tests early on.&lt;/p&gt;
&lt;h2 id=&#34;a-virtual-machine&#34;&gt;A Virtual Machine&lt;/h2&gt;
&lt;p&gt;This chapter is mostly straightforward, except for a few shenanigans we have to make because Zig is different.
The first thing I would like to talk about is pointers in various programming languages.&lt;/p&gt;
&lt;p&gt;In C we &lt;em&gt;basically&lt;/em&gt; have one kind of pointer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;SomeType * variable;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This really can be anything.
It can be a pointer to a single location, or it can be a pointer to an array, or even to a place somewhere in a set array.
Well, there&amp;rsquo;s also a function pointer in C, but we&amp;rsquo;re not going to look at it now.&lt;/p&gt;
&lt;p&gt;Zig, on the other hand, has quite a few types of pointers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;*T&lt;/code&gt; - single-item pointer to exactly one item.
&lt;ul&gt;
&lt;li&gt;Supports deref syntax: &lt;code&gt;ptr.*&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[*]T&lt;/code&gt; - many-item pointer to an unknown number of items.
&lt;ul&gt;
&lt;li&gt;Supports index syntax: &lt;code&gt;ptr[i]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Supports slice syntax: &lt;code&gt;ptr[start..end]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Supports pointer arithmetic: &lt;code&gt;ptr + x&lt;/code&gt;, &lt;code&gt;ptr - x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;T&lt;/code&gt; must have a known size&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;*[N]T&lt;/code&gt; - pointer to N items, same as a single-item pointer to an array.
&lt;ul&gt;
&lt;li&gt;Supports index syntax: &lt;code&gt;array_ptr[i]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Supports slice syntax: &lt;code&gt;array_ptr[start..end]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Supports len property: &lt;code&gt;array_ptr.len&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;[]T&lt;/code&gt; - is a slice (a fat pointer, which contains a pointer of type &lt;code&gt;[*]T&lt;/code&gt; and a length).
&lt;ul&gt;
&lt;li&gt;Supports index syntax: &lt;code&gt;slice[i]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Supports slice syntax: &lt;code&gt;slice[start..end]&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Supports len property: &lt;code&gt;slice.len&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As you can see, we can&amp;rsquo;t just write &lt;code&gt;variable: *SomeType&lt;/code&gt; in Zig and use it like we can in C.
I believe this is a good thing, and in practice, it does eliminate bugs related to accessing ordinary pointers as arrays.
On the other hand, it is quite tedious to write code with such a system.&lt;/p&gt;
&lt;p&gt;To get what I mean, let&amp;rsquo;s have a look at how the instruction pointer concept is implemented by the book:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Chunk* chunk;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;uint8_t&lt;/span&gt;* ip;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} VM;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;InterpretResult &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interpret&lt;/span&gt;(Chunk* chunk) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  vm.chunk = chunk;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  vm.ip = vm.chunk-&amp;gt;code;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; run();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You&amp;rsquo;re looking at the &lt;code&gt;VM&lt;/code&gt; struct that holds the currently executed &lt;code&gt;chunk&lt;/code&gt; and an instruction pointer &lt;code&gt;ip&lt;/code&gt;.
In the &lt;code&gt;interpret&lt;/code&gt; function we set the VM&amp;rsquo;s current chunk, and its instruction pointer to point to the &lt;code&gt;code&lt;/code&gt; from the chunk.
As you may remember the &lt;code&gt;Chunk&lt;/code&gt; struct contains the &lt;code&gt;code&lt;/code&gt; field which is a dynamic array: &lt;code&gt;uint8_t * code&lt;/code&gt;.
So by saying &lt;code&gt;vm.ip = vm.chunk-&amp;gt;code&lt;/code&gt; we essentially say that &lt;code&gt;ip&lt;/code&gt; now holds the same address that was in the &lt;code&gt;code&lt;/code&gt; field.
Hopefully, it&amp;rsquo;s the start of the array!&lt;/p&gt;
&lt;p&gt;With that, we can now inspect the &lt;code&gt;run&lt;/code&gt; function.
For now, all we really care about is how it uses the instruction pointer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;static&lt;/span&gt; InterpretResult &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;run&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#define READ_BYTE() (*vm.ip++)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (instruction = READ_BYTE()) {&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/* ... */&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#undef READ_BYTE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Aha, C tricks!
The &lt;code&gt;READ_BYTE&lt;/code&gt; is a substitution macro that simply increments the pointer with &lt;code&gt;++&lt;/code&gt;, dereferencing the resulting one with &lt;code&gt;*&lt;/code&gt;.
It&amp;rsquo;s a clever trick - too clever, even, because of the operator precedence rules in C.
The &lt;code&gt;++&lt;/code&gt; has to happen &lt;strong&gt;before&lt;/strong&gt; &lt;code&gt;*&lt;/code&gt; because otherwise, we would increment the dereferenced value.
But the effect of &lt;code&gt;++&lt;/code&gt; has to happen &lt;strong&gt;after&lt;/strong&gt; we dereference the pointer, otherwise, we would dereference the &lt;em&gt;next&lt;/em&gt; address.
This code can be rewritten into two separate expressions, like &lt;code&gt;uint8_t val = *ip; ip = ip + 1;&lt;/code&gt; but it&amp;rsquo;s hard to use that in a macro, that itself is used in the expression context.
So the &lt;code&gt;*ptr++&lt;/code&gt; form is a quite common trick.&lt;/p&gt;
&lt;p&gt;But here&amp;rsquo;s the thing - the &lt;code&gt;ip&lt;/code&gt; is not an array, it just happens to hold an address to an array.
Uh oh.&lt;/p&gt;
&lt;p&gt;Well, that&amp;rsquo;s a common thing in C, so let&amp;rsquo;s look at Zig.
Now, I&amp;rsquo;m not really experienced in Zig&amp;rsquo;s pointers but after poking around I think we have several options:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; VM = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk: *Chunk, &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// store a pointer to the chunk
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    ip: []Code, &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// and a fat pointer to the array
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// methods ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 6:&lt;/span&gt;
  Option №1
&lt;/div&gt;
&lt;p&gt;Here I have the &lt;code&gt;[*]T&lt;/code&gt; type of pointer because we&amp;rsquo;re going to point to an array because the &lt;code&gt;Chunk&lt;/code&gt; stores items in a dynamic array.
We can implement the &lt;code&gt;interpret&lt;/code&gt; and &lt;code&gt;run&lt;/code&gt; functions as follows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; interpret(self: *VM, chunk: *Chunk) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.chunk = chunk;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.ip = chunk.code.items;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.run();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; run(self: *VM) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; instr = self.ip[0]; self.ip += 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (instr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can put the pointer reading into an &lt;code&gt;inline&lt;/code&gt; function, but that&amp;rsquo;s beside the point.
Look at how we have to dereference this kind of pointer: &lt;code&gt;ip[0]&lt;/code&gt;.
Unlike in C, we can&amp;rsquo;t use a single-item pointer dereference syntax here, because it&amp;rsquo;s not a single-item pointer!&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try a single-item pointer then:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; VM = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk: *Chunk, &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// store a pointer to the chunk
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    ip: *Code, &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// and a pointer to a place in the array
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// methods ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 7:&lt;/span&gt;
  Option №2
&lt;/div&gt;
&lt;p&gt;Now we have a single-item pointer for the instruction pointer (makes sense), but let&amp;rsquo;s look at how we have to use it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; interpret(self: *VM, chunk: *Chunk) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.chunk = chunk;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.ip = &amp;amp;chunk.code.items[0];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.run();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; run(self: *VM) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; instr = self.ip.*;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.ip = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@ptrCast&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;([*]Code, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@ptrCast&lt;/span&gt;(self.ip)) + 1);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (instr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ugh, that&amp;rsquo;s looking nasty.
We have to do two pointer casts to do a simple thing like that.
Looking at it now the &lt;code&gt;ip[0]&lt;/code&gt; doesn&amp;rsquo;t look that out of place.&lt;/p&gt;
&lt;p&gt;But then the book does this kind of thing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;disassembleInstruction(vm.chunk, (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt;)(vm.ip - vm.chunk-&amp;gt;code));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you recall the &lt;code&gt;disassembleInstruction&lt;/code&gt; signature, the second argument is an integer offset.
So we do all this pointer arithmetic here and there just to convert it back to an index in the array.
And that&amp;rsquo;s our option three:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; VM = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    chunk: *Chunk, &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// store a pointer to the chunk
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    ip: []Code,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ic: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;, &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// and an index!
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// methods ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 8:&lt;/span&gt;
  Option №3
&lt;/div&gt;
&lt;p&gt;This does require a bit different approach in the rest of the code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; interpret(self: *VM, chunk: *Chunk) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self.chunk = chunk;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self.ip = chunk.code.items;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    self.ic = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.run();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; run(self: *VM) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; instr = self.ip[self.ic]; self.ic += 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (instr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can simply use the &lt;code&gt;vm.disassembleInstruction(self.ip)&lt;/code&gt; to disassemble the instruction avoiding all of the pointer arithmetic altogether.
Now, I&amp;rsquo;m sure the raw pointer for this kind of task is more appealing, and probably it is slightly faster.
But to me, this looks like a premature optimization, at least for now.
So that&amp;rsquo;s the way I decided to do it for my implementation.&lt;/p&gt;
&lt;p&gt;Another thing I want to touch here is the return type of the &lt;code&gt;interpret&lt;/code&gt; function.
In the book, the return type is called &lt;code&gt;InterpretResult&lt;/code&gt; and it is a enumeration with simple tags: &lt;code&gt;INTERPRET_OK&lt;/code&gt;, &lt;code&gt;INTERPRET_COMPILE_ERROR&lt;/code&gt;, &lt;code&gt;INTERPRET_RUNTIME_ERROR&lt;/code&gt;.
When we reach the &lt;code&gt;OP_RETURN&lt;/code&gt; the result of the &lt;code&gt;run&lt;/code&gt; function is the &lt;code&gt;INTERPRET_OK&lt;/code&gt; tag.
At the end of the chapter, after we&amp;rsquo;ve implemented the stack and basic arithmetic operations we read the last value on the stack and print it before we exit:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; OP_RETURN: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        printValue(pop());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        printf(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; INTERPRET_OK;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While this is in the spirit of C, we can do better.
And in fact, we have to do better, as we need to write tests, as the book suggested.
It&amp;rsquo;s hard to write tests if you don&amp;rsquo;t have access to the result of interpretation, so my &lt;code&gt;Result&lt;/code&gt; type is defined as &lt;code&gt;union(enum)&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Result = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    OK: Value,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    CompileError,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    RuntimeError,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way we can return the actual value instead of printing it, and indicate that everything is OK at the same time, kinda like Rust&amp;rsquo;s &lt;code&gt;Option&lt;/code&gt; type:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// switch(opcode) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;           .Ret =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; .{ .OK = self.pop() },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way we can check the results in our VM tests.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve omitted a bunch of stuff from this chapter, but simply because there aren&amp;rsquo;t many interesting things there when it comes to Zig vs C.
But one thing I would like to return to is metaprogramming, because this book does it frequently enough to be a hassle.
We&amp;rsquo;ve already seen a bunch of &lt;code&gt;#define&lt;/code&gt; directives in the C examples above, and the book goes pretty far with them, defining a polymorphic &lt;code&gt;BINARY_OP&lt;/code&gt; macro:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#define BINARY_OP(op) \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;    do { \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;      double b = pop(); \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;      double a = pop(); \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;      push(a op b); \
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;    } while (false)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;do {...} while(false)&lt;/code&gt; is a common trick in C macros.
For those unfamiliar with how &lt;code&gt;do while&lt;/code&gt; works, as it is rarely seen in other languages, it executes the body first, then checks the condition and repeats if it is true.
Classical &lt;code&gt;while&lt;/code&gt; checks the condition first.
Most languages omit &lt;code&gt;do while&lt;/code&gt; because it is essentially the same as writing the body of the while loop two times, e.g.:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo();           &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// do {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (test()) { &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;//    foo();
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    foo();       &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// } while (test());
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Of course, there are other ways to rewrite this code, and &lt;code&gt;do while&lt;/code&gt; looks clearer, but it&amp;rsquo;s quite rare.
In our case though, it is used as a way to introduce a valid language construct that allows for a semicolon to be inserted after it.
Because of that, it uses &lt;code&gt;while(false)&lt;/code&gt; i.e. it never loops.&lt;/p&gt;
&lt;p&gt;So when you write &lt;code&gt;BINARY_OP(+);&lt;/code&gt; (mind the semicolon) it expands to the correct code with a semicolon after &lt;code&gt;while (false);&lt;/code&gt; which is required in the case of this language construct, unlike with other loops.
Yep, that&amp;rsquo;s the sole reason it is used here, and compilers are smart enough to detect that the loop will never happen, so they omit the loop entirely.
A truly sad state of metaprogramming, and expression statements in C.&lt;/p&gt;
&lt;p&gt;However, Zig doesn&amp;rsquo;t have macros.
Instead, it has the &lt;code&gt;comptime&lt;/code&gt; keyword, which marks the expression or function argument to be used only at compilation time.
Unfortunately, there doesn&amp;rsquo;t seem to be a way to write an inline comptime function that will accept an operator and return some kind of AST, or other code to be present in the expression.
We can work around it, though:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; binaryOp(op: OPCode, a: Value, b: Value) Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (op) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .Add =&amp;gt; a + b,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .Sub =&amp;gt; a - b,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .Mul =&amp;gt; a * b,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .Div =&amp;gt; a / b,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ---8&amp;lt;---
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;   &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;//       switch(opcode) {
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;                .Add, .Sub, .Mul, .Div =&amp;gt; |instr| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; b = self.pop();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; sp = self.stack_top - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    sp[0] = binaryOp(instr, sp[0], b);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// }
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not as pretty, but works, I guess.
We do have a cost of doing branching twice, e.g. first in the &lt;code&gt;run&lt;/code&gt; function, then in the &lt;code&gt;binaryOp&lt;/code&gt; function, even though by the time we&amp;rsquo;re in &lt;code&gt;binaryOp&lt;/code&gt; we already know what operation we&amp;rsquo;re dealing with.
C&amp;rsquo;s macros are giving us the ability to construct code without explicit copy-pasting and without explicit re-branching.
We can avoid re-branching by writing it like this, of course:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; add(self: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; b = self.pop();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; sp = self.stack_top - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sp[0] = sp[0] + b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; sub(self: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; b = self.pop();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; sp = self.stack_top - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sp[0] = sp[0] - b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; div(self: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; b = self.pop();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; sp = self.stack_top - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sp[0] = sp[0] / b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; mul(self: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; b = self.pop();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; sp = self.stack_top - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        sp[0] = sp[0] * b;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; run(self: *Self) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (opcode) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;                .Add =&amp;gt; self.add(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Sub =&amp;gt; self.sub(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Mul =&amp;gt; self.mul(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Div =&amp;gt; self.div(),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But now you see clearly what parts of the code can be easily generated, all these functions only differ by their name.
Unfortunately, Zig&amp;rsquo;s &lt;code&gt;comptime&lt;/code&gt; isn&amp;rsquo;t capable of treating operators as values, so we can&amp;rsquo;t write something like &lt;code&gt;self.binaryOp(-)&lt;/code&gt; and handle it at compilation time to produce the body.
Oh well, Lisp macros have spoiled me, I guess.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s like the only part I have an issue with in this language.
The author is very vocal about macros, but after speaking with them on IRC a few times it seems to me that they only saw C macros and, maybe, C++ templates, and were like: &amp;ldquo;Yikes, macros are bad!&amp;rdquo;.
We&amp;rsquo;ve been manipulating code as data with macros since the 60s, people did a lot of research creating safer ways to write macros, then the C preprocessor comes along and now everybody shits on macros because text substitutions are bad.
Of course, they are!
What baffles me the most is that among lispers there are people who are equally vocal about how bad macros are and that you should never write ones.
I guess I&amp;rsquo;ll write another post about that, adding another hit to the horse.&lt;/p&gt;
&lt;h2 id=&#34;scanning-on-demand&#34;&gt;Scanning on Demand&lt;/h2&gt;
&lt;p&gt;This chapter starts painfully.
Well, painfully isn&amp;rsquo;t the right word really, but it introduces a lot of inconvenience by breaking our &lt;code&gt;main&lt;/code&gt; function.&lt;/p&gt;
&lt;p&gt;At the start of the chapter, we&amp;rsquo;re introduced to two basic workflows our executable will support - run a &lt;abbr title=&#34;Read Eval Print Loop&#34;&gt;&amp;ldquo;REPL&amp;rdquo;&lt;/abbr&gt; or run a file.
And that brings me to my pain point - why doesn&amp;rsquo;t Zig have any kind of a REPL?
Again, I&amp;rsquo;m spoiled by lisps, but it&amp;rsquo;s so liberating to have a broken program, yet still be able to call functions from the REPL, gradually fixing the program.
Here, I&amp;rsquo;m basically stripped of any way to run any code, until I make the whole source work again.
Well, that&amp;rsquo;s the downside of the edit compile run cycle, but lisps are compiled languages that don&amp;rsquo;t have such a problem.
The compilation&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt; just happens in the REPL.&lt;/p&gt;
&lt;p&gt;As a matter of fact, the &lt;code&gt;main&lt;/code&gt; function will be broken for the entirety of this chapter.&lt;/p&gt;
&lt;p&gt;This nitpick aside, we&amp;rsquo;re finally starting to work on the parser.
Unfortunately, this chapter isn&amp;rsquo;t interesting on its own, when it comes to implementing this in Zig.
Same tricks with pointers replaced by integers, and pretty much the same code otherwise.&lt;/p&gt;
&lt;p&gt;Still not sure why the chapter required to break &lt;code&gt;main&lt;/code&gt; if we never actually used it.
It will make more sense as the part of second chapter.&lt;/p&gt;
&lt;h2 id=&#34;compiling-expressions&#34;&gt;Compiling Expressions&lt;/h2&gt;
&lt;p&gt;In the spirit of the previous chapter, the breakage continues.
Remember how I said that writing tests during this book will result in lots of test rewriting due to constant refactoring?
This is probably the first, but not the last instance of this - we&amp;rsquo;ve changed the &lt;code&gt;interpret&lt;/code&gt; signature to accept the source code instead of a chunk.&lt;/p&gt;
&lt;p&gt;This broke all of my VM tests, though, thankfully, I only had just one at this point.
Actually, I don&amp;rsquo;t like this change, to be honest, I&amp;rsquo;d much rather preserve the old signature, as the VM interprets the bytecode, not the source code.
The bytecode doesn&amp;rsquo;t have to come from the source code, it can come from anywhere, and hence it should be what the function accepts.
Instead, we create the chunk inside the &lt;code&gt;interpret&lt;/code&gt; function and fill it with the compiler.
Oh well, I&amp;rsquo;m not a language designer proper, so I guess I should not complain.&lt;/p&gt;
&lt;p&gt;Anyway, this chapter is interesting.
We&amp;rsquo;re actually starting to compile our language from source code into bytecode, and that&amp;rsquo;s cool.
The parser itself is quite concise, and I like how it is implemented so far.
One interesting thing I&amp;rsquo;d like to point out is how the book defines the rules:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ParseRule rules[] = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_LEFT_PAREN]    = {grouping, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_RIGHT_PAREN]   = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_LEFT_BRACE]    = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_RIGHT_BRACE]   = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_COMMA]         = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_DOT]           = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_MINUS]         = {unary,    binary, PREC_TERM},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_PLUS]          = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     binary, PREC_TERM},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_SEMICOLON]     = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_SLASH]         = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     binary, PREC_FACTOR},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_STAR]          = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     binary, PREC_FACTOR},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_BANG]          = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_NUMBER]        = {number,   &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;  [TOKEN_ERROR]         = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [TOKEN_EOF]           = {&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,     &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;NULL&lt;/span&gt;,   PREC_NONE},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;static&lt;/span&gt; ParseRule* &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;getRule&lt;/span&gt;(TokenType type) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &amp;amp;rules[type];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is when C looks nice and beautiful (if you can say so).
The fact that enumerations in C are just numbers has a lot of problems, but sometimes it&amp;rsquo;s cool because you can use them as array indexes.&lt;/p&gt;
&lt;p&gt;As for Zig, I couldn&amp;rsquo;t find if it has a way to do the same thing.
Mainly because you can&amp;rsquo;t initialize an array using enumeration tags as indexes.&lt;/p&gt;
&lt;p&gt;Using &lt;code&gt;zig translate-c&lt;/code&gt; on this simplified example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    TOKEN_RIGHT_PAREN,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    TOKEN_LEFT_BRACE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    TOKEN_RIGHT_BRACE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    TOKEN_COMMA,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    TOKEN_DOT,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} TokenType;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PREC_A,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PREC_B,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PREC_C,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    PREC_D,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} Precedence;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Precedence precedence;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} ParseRule;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ParseRule rules[] = {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [TOKEN_LEFT_BRACE]    = {PREC_A},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [TOKEN_DOT]           = {PREC_B},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [TOKEN_RIGHT_BRACE]   = {PREC_C},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    [TOKEN_RIGHT_PAREN]   = {PREC_D},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We get the following Zig code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// .. tons of definitions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; TOKEN_RIGHT_PAREN: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; TOKEN_LEFT_BRACE: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; TOKEN_RIGHT_BRACE: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; TOKEN_COMMA: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 3;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; TOKEN_DOT: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 4;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; TokenType = &lt;span style=&#34;font-weight:bold&#34;&gt;c_uint&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; PREC_A: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; PREC_B: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; PREC_C: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; PREC_D: &lt;span style=&#34;font-weight:bold&#34;&gt;c_int&lt;/span&gt; = 3;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Precedence = &lt;span style=&#34;font-weight:bold&#34;&gt;c_uint&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; ParseRule = &lt;span style=&#34;font-weight:bold&#34;&gt;extern&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    precedence: Precedence,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; rules: [5]ParseRule = [5]ParseRule{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ParseRule{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .precedence = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;c_uint&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@bitCast&lt;/span&gt;(PREC_D)),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ParseRule{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .precedence = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;c_uint&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@bitCast&lt;/span&gt;(PREC_A)),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ParseRule{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .precedence = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;c_uint&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@bitCast&lt;/span&gt;(PREC_C)),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;std&amp;#34;&lt;/span&gt;).mem.zeroes(ParseRule),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ParseRule{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .precedence = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;c_uint&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@bitCast&lt;/span&gt;(PREC_B)),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// .. tons of more definitions
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Looks like Zig doesn&amp;rsquo;t have a syntax like that, suggested by the fact that it sorted elements of the array based on the enumeration tag values.
But that practically removes any benefits of using enumerations in such a way, as we&amp;rsquo;re forced to keep the order ourselves.
Perhaps, there&amp;rsquo;s a way to do that using &lt;code&gt;comptime&lt;/code&gt;, but I&amp;rsquo;m not that good with Zig.
So, I did it like that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; makeRules() []ParseRule {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; r = [_]ParseRule{&lt;span style=&#34;font-weight:bold&#34;&gt;undefined&lt;/span&gt;} ** &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeInfo&lt;/span&gt;(TokenType).Enum.fields.len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.LEFT_PAREN)] = .{ .prefix = Parser.grouping, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .CALL };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.RIGHT_PAREN)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.LEFT_BRACE)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.RIGHT_BRACE)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.COMMA)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.DOT)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.MINUS)] = .{ .prefix = Parser.unary, .infix = Parser.binary, .precedence = .TERM };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.PLUS)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = Parser.binary, .precedence = .TERM };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.SEMICOLON)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.SLASH)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = Parser.binary, .precedence = .FACTOR };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.STAR)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = Parser.binary, .precedence = .FACTOR };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.BANG)] = .{ .prefix = Parser.unary, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.NUMBER)] = .{ .prefix = Parser.number, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.ERROR)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    r[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(TokenType.EOF)] = .{ .prefix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .infix = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, .precedence = .NONE };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &amp;amp;r;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; rules = makeRules();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; getRule(t: TokenType) ParseRule {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; rules[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(t)];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It works, looks awful.&lt;/p&gt;
&lt;p&gt;Apart from that, the chapter is pretty straightforward.
Another thing I want to point out is the fact that C supports compilation flags out of the box, and Zig doesn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;Well, in C it is a hot mess, but it works reliably enough to see it as a feature in my opinion:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#define DEBUG_PRINT_CODE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// later in the code
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#ifdef DEBUG_PRINT_CODE
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// compile-time code injection
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#888;font-weight:bold&#34;&gt;#endif
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Next, when compiling the code, you can supply &lt;code&gt;-DDEBUG_PRINT_CODE&lt;/code&gt; to the compiler and it will set this to &lt;em&gt;something&lt;/em&gt; so the &lt;code&gt;#ifdef&lt;/code&gt; directive contents will be included in the resulting source code.&lt;/p&gt;
&lt;p&gt;In Zig, there&amp;rsquo;s again &lt;code&gt;comptime&lt;/code&gt; and I guess writing &lt;code&gt;if (comptime DEBUG_PRINT_CODE) { ... }&lt;/code&gt; would include/eliminate the code at compile time, but how do we supply it to the compiler?
The answer is the build system of Zig, which itself is just a program written in Zig.
And again, I feel that this is way too complicated than it should be, especially since I have tests in a separate directory, and I have to pass compilation options to tests as well as to the main executable.
I didn&amp;rsquo;t bother with that in the end.&lt;/p&gt;
&lt;p&gt;Finally, &lt;em&gt;challenges&lt;/em&gt;.
This chapter has a decent set of &lt;em&gt;challenges&lt;/em&gt;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt;, except for the last one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;You might be wondering about complex “mixfix” expressions that have more than two operands separated by tokens.
C’s conditional or “ternary” operator, &lt;code&gt;?:&lt;/code&gt;, is a widely known one.&lt;/p&gt;
&lt;p&gt;Add support for that operator to the compiler.
You don’t have to generate any bytecode, just show how you would hook it up to the parser and handle the operands.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;First, no - why would you need to implement &lt;code&gt;?:&lt;/code&gt; before we have implemented &lt;code&gt;if&lt;/code&gt; itself?
Second - why implement &lt;code&gt;?:&lt;/code&gt; at all if we&amp;rsquo;re implementing the new language and can make &lt;code&gt;if&lt;/code&gt; to be an expression?
I understand that this is a small and simple language, but the &lt;code&gt;if&lt;/code&gt; expressions can be a great way to introduce people to the concept of familiar statements being expressions as well.&lt;/p&gt;
&lt;h2 id=&#34;types-of-values&#34;&gt;Types of Values&lt;/h2&gt;
&lt;p&gt;This chapter begins with a paragraph I can connect with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The nice thing about working in C is that we can build our data structures from the raw bits up.
The bad thing is that we have to do that.
C doesn’t give you much for free at compile time and even less at runtime.
As far as C is concerned, the universe is an undifferentiated array of bytes.
It’s up to us to decide how many of those bytes to use and what they mean.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Indeed, when I was working with C this was always the case.
On one hand, it&amp;rsquo;s problematic, on the other, it is empowering.
But I&amp;rsquo;m doing this book&amp;rsquo;s project in Zig and I can&amp;rsquo;t say that Zig is the same as C in this regard.
Instead of doing things the C way, Zig provides more high-level concepts to us, like union enums, and such.
So let&amp;rsquo;s try to use these instead.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how we implement the &lt;code&gt;Value&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Number: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Bool: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; print(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (self) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .Number =&amp;gt; |value| std.debug.print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{d}&amp;#34;&lt;/span&gt;, .{value}),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .Bool =&amp;gt; |value| std.debug.print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;, .{value}),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .Nil =&amp;gt; std.debug.print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;nil&amp;#34;&lt;/span&gt;, .{}),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In its essence, it&amp;rsquo;s similar to the union in the book:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  VAL_BOOL,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  VAL_NIL,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  VAL_NUMBER,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} ValueType;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ValueType type;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; boolean;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;double&lt;/span&gt; number;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } as;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} Value;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, as an added bonus, we can add methods to our &lt;code&gt;Value&lt;/code&gt; type, the same as with other &lt;code&gt;struct&lt;/code&gt;&amp;rsquo;s.
As you can see, the &lt;code&gt;print&lt;/code&gt; function is a part of the &lt;code&gt;union(enum)&lt;/code&gt; and can be invoked as &lt;code&gt;val.print()&lt;/code&gt; later in the code.&lt;/p&gt;
&lt;p&gt;Once again, we have to change parts of our code that are quite basic, but nothing too breaking this time.
All I had to do was wrap numbers into the &lt;code&gt;Value&lt;/code&gt; constructor in a few tests.
This is just the beginning though, we have to make more &lt;code&gt;Value&lt;/code&gt; sub-types for strings, and objects.&lt;/p&gt;
&lt;h2 id=&#34;strings&#34;&gt;Strings&lt;/h2&gt;
&lt;p&gt;Now, this is where my previous attempt at this book in Zig train-wrecked.
Or, should I say, it was the beginning of the end for that implementation.
You see, til now, most concepts introduced by the book were easy enough to translate from C to Zig, because most of the time the stuff was either the same or already backed by Zig&amp;rsquo;s standard library.
For example, at the start of the book, I decided not to implement dynamic arrays, because:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I already made my fair share of dynamic arrays in C back when I was a C programmer&lt;/li&gt;
&lt;li&gt;After looking at what the book suggests, and the implementation in Zig&amp;rsquo;s standard library, they&amp;rsquo;re practically the same, with some small changes that are irrelevant for the matter.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Other stuff was pretty much the same, except for, perhaps, how pointers are used - instead I used offsets most of the time, as it is easier to do.
Unions and enumerations are again similar, though with some small differences, like being able to use &lt;code&gt;union(enum)&lt;/code&gt; and add methods onto it, but again, C code kinda does the same thing, just &lt;em&gt;the C way&lt;/em&gt;.
Strings, however, are a different beast.
They&amp;rsquo;re objects, and hence they&amp;rsquo;re dynamically typed because objects kinda are.
E.g. in Lox string is an object, a function is also an object, and a class also is an object, and we have to express this idea somehow in C/Zig.
Here&amp;rsquo;s how the book does it in C:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;typedef&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  OBJ_STRING,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;} ObjType;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; Obj {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ObjType type;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is only a &lt;code&gt;struct&lt;/code&gt; definition for the object type, but there&amp;rsquo;s a certain trick that we can do in C by abusing the fact that structure layouts are consistent.
We can create a second structure like this one:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; ObjString {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  Obj obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; length;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;char&lt;/span&gt;* chars;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, here&amp;rsquo;s an interesting part - we can convert a pointer between these two structs at will!
It is possible because the memory layout between the first field in the &lt;code&gt;ObjString&lt;/code&gt; and the entirety of &lt;code&gt;Obj&lt;/code&gt; &lt;code&gt;struct&lt;/code&gt; is the same.
Now, since the first field in the &lt;code&gt;struct&lt;/code&gt; has the same address as the &lt;code&gt;struct&lt;/code&gt; itself, i.e. an offset of &lt;code&gt;0&lt;/code&gt;, and the &lt;code&gt;struct&lt;/code&gt; field size is the same as its type, given the pointer to &lt;code&gt;ObjString&lt;/code&gt; we can cast it to &lt;code&gt;Obj&lt;/code&gt; and read its fields as normal.&lt;/p&gt;
&lt;p&gt;But how do we do that in Zig?
Zig&amp;rsquo;s structs are much more than C structs, as they can have methods, we can manipulate field types at compile time, and so on.
My first approach was like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; LoxString = []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; LoxObject = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    next: ?*LoxObject,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data: &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        String: LoxString,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; objType(self: LoxObject) Tag(LoxObject) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; activeTag(self.data);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isString(self: LoxObject) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (self.data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .String =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; allocString(s: LoxString, vm: *VM(Code), allocator: Allocator) *LoxObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; obj = allocator.create(LoxObject) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt; exit(123, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Not enough memory to allocate object&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (obj.*.data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .String =&amp;gt; |*value| value.* = s,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        obj.next = vm.objects;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        vm.objects = obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; freeObject(obj: *LoxObject, allocator: Allocator) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (obj.*.data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .String =&amp;gt; |s| allocator.free(s),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        allocator.destroy(obj);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, I decided to store the underlying data of the object in the &lt;code&gt;union(enum)&lt;/code&gt;, similarly to how I do that for &lt;code&gt;Value&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Number: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Bool: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Obj: *Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Later, when we added more object types, this became a problem.
This layout means that I can&amp;rsquo;t cast the &lt;code&gt;LoxObject&lt;/code&gt; to a &lt;code&gt;LoxString&lt;/code&gt;, and I can&amp;rsquo;t really access it without going through the union:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;test&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;string concatenation&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; vm = VM(Code).init(allocator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;defer&lt;/span&gt; vm.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (interpret(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;a&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt; + &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;b&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;, &amp;amp;vm).OK) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        .Obj =&amp;gt; |obj| &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (obj.*.data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .String =&amp;gt; |s| expectEqualSlices(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, s, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;ab&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The code was filled with these &lt;code&gt;obj.*.data&lt;/code&gt; switches, that extracted the string.
And later on, at some point, I had really weird bugs, like when my &lt;code&gt;isString&lt;/code&gt; function returns &lt;code&gt;true&lt;/code&gt;, but when I try to access the string, I get the error &amp;ldquo;trying to access the inactive field of enumeration&amp;rdquo;.
Be it a bug in Zig itself or in my code I don&amp;rsquo;t care.&lt;/p&gt;
&lt;p&gt;Since then I changed the implementation to be more like in the book:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 1
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 2
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 3
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 4
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 5
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 6
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 7
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 8
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;16
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;37
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;38
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;39
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;40
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;41
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;42
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;43
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;44
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;45
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;46
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;47
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;48
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;49
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;50
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Type = &lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    String,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Obj = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    objType: Type,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    next: ?*Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; allocate(vm: *VM, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; T: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;, objType: Type) *Obj {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; ptr = vm.allocator.create(T) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Common.exit(200, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OOME: can&amp;#39;t allocate object&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ptr.obj = Obj{ .objType = objType, .next = vm.objects };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        vm.objects = &amp;amp;ptr.obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &amp;amp;ptr.obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asString(self: *Obj) *String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@fieldParentPtr&lt;/span&gt;(String, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obj&amp;#34;&lt;/span&gt;, self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; destroy(self: *Obj, vm: *VM) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (self.objType) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .String =&amp;gt; self.asString().destroy(vm),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; String = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    obj: Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bytes: []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; create(vm: *VM, bytes: str) *String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; obj = Obj.allocate(vm, String, .String);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; out = obj.asString();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        out.* = String{ .obj = obj.*, .bytes = bytes };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; out;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; copy(vm: *VM, source: str) *String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; buffer = vm.allocator.alloc(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, source.len) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Common.exit(200, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OOME: can&amp;#39;t allocate string&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        std.mem.copy(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, buffer, source);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; String.create(vm, buffer);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; destroy(self: *String, vm: *VM) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        vm.allocator.free(self.bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        vm.allocator.destroy(self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now, this &lt;code&gt;@fieldParentPtr&lt;/code&gt; feels sketchy with its &lt;code&gt;&amp;quot;obj&amp;quot;&lt;/code&gt; parameter.
It is supposed to be a field name, and I find string a weird choice as strings can contain arbitrary data, while field names can&amp;rsquo;t.
But that&amp;rsquo;s beside the point, let&amp;rsquo;s look at it a bit closer:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asString(self: *Obj) *String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@fieldParentPtr&lt;/span&gt;(String, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obj&amp;#34;&lt;/span&gt;, self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The signature of this &lt;em&gt;builtin&lt;/em&gt; is as follows: &lt;code&gt;comptime ParentType: type&lt;/code&gt;, &lt;code&gt;comptime field_name: []const u8&lt;/code&gt;, &lt;code&gt;field_ptr: *T&lt;/code&gt;, and the return type is a pointer to the &lt;code&gt;ParentType&lt;/code&gt;.
As you can see, the usage is interesting - we pass the desired type &lt;code&gt;String&lt;/code&gt; which is a different &lt;code&gt;struct&lt;/code&gt;.
Then we pass the &lt;code&gt;&amp;quot;obj&amp;quot;&lt;/code&gt; field name, and the last parameter should be a pointer to a field, for which we use the object pointer itself.&lt;/p&gt;
&lt;p&gt;Presumably, Zig knows its memory layout and can calculate the offset to the base &lt;code&gt;struct&lt;/code&gt; given a field pointer.
Indeed, knowing the layout and giving a pointer to a field, it is possible to calculate the start of the struct, however, in this case, we do it a bit weird, as we get a pointer to the &lt;code&gt;Obj&lt;/code&gt; structure, which doesn&amp;rsquo;t have the &lt;code&gt;obj&lt;/code&gt; field at all.
We then use this pointer as a third parameter, i.e. as a pointer to the field of the &lt;code&gt;String&lt;/code&gt; structure.
Therefore, this built-in calculates the width of the &lt;code&gt;obj&lt;/code&gt; field, subtracts it from the pointer address, and returns the pointer to the &lt;code&gt;base struct&lt;/code&gt; but as the &lt;code&gt;String&lt;/code&gt; type.&lt;/p&gt;
&lt;p&gt;Overall, this looks like what we do in C, except we use &lt;code&gt;@fieldParentPtr&lt;/code&gt; to do the pointer casting.
We can see it being used in the &lt;code&gt;create&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;36
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;37
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; create(vm: *VM, bytes: str) *String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; obj = Obj.allocate(vm, String, .String);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; out = obj.asString();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        out.* = String{ .obj = obj.*, .bytes = bytes };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; out;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;We have the object allocated as a &lt;code&gt;String&lt;/code&gt;, ensuring the memory layout, but then we assign the &lt;code&gt;.obj&lt;/code&gt; field an &lt;code&gt;Obj&lt;/code&gt; structure, finally returning a pointer to this field:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt; 9
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;10
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;11
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;12
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;13
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;14
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; allocate(vm: *VM, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; T: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;, objType: Type) *Obj {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; ptr = vm.allocator.create(T) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            Common.exit(200, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OOME: can&amp;#39;t allocate object&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ptr.obj = Obj{ .objType = objType, .next = vm.objects };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        vm.objects = &amp;amp;ptr.obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &amp;amp;ptr.obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Everything should now make sense - we indeed have the pointer to the &lt;code&gt;obj&lt;/code&gt; field by the time we get to use the &lt;code&gt;asString&lt;/code&gt; function, but we always have the pointer to the &lt;code&gt;Obj&lt;/code&gt; at hand.&lt;/p&gt;
&lt;p&gt;In other words, it&amp;rsquo;s not as in C where we literally convert a single pointer between two different layouts, abusing the fact that the memory layout allows for it.
Instead, we can have a pointer to anywhere inside the struct and still get the correct parent pointer thanks to the known memory layout.
We could do the same in C but it would be more work, and far more error-prone, as we would need to compute this offset manually.
Here, Zig has us covered.&lt;/p&gt;
&lt;p&gt;Overall, I like this approach more, I guess.
C&amp;rsquo;s way of doing this feels like a clever memory trick, while Zig&amp;rsquo;s way of doing this is more of a compiler-supported way.&lt;/p&gt;
&lt;h2 id=&#34;hash-tables&#34;&gt;Hash Tables&lt;/h2&gt;
&lt;p&gt;Now, in my previous attempt I thought to myself: &amp;ldquo;Well, I skipped the dynamic array, let&amp;rsquo;s at least implement a hash table&amp;rdquo;.
As a result, I ended up looking at how the hash table is implemented in Zig&amp;rsquo;s standard library.
Now, I&amp;rsquo;m not sure if my implementation was correct, but it seemed that way.&lt;/p&gt;
&lt;p&gt;Looking at it now, I&amp;rsquo;m not sure if I could use a hash table from Zig&amp;rsquo;s standard library, as it needs custom hashing.
I probably can implement some kind of interface for the objects that would allow me to hash them.
So let&amp;rsquo;s look into that:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// General purpose hash table.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// No order is guaranteed and any modification invalidates live iterators.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// It provides fast operations (lookup, insertion, deletion) with quite high
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// load factors (up to 80% by default) for low memory usage.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// For a hash map that can be initialized directly that does not store an Allocator
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// field, see `HashMapUnmanaged`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// If iterating over the table entries is a strong usecase and needs to be fast,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// prefer the alternative `std.ArrayHashMap`.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// Context must be a struct type with two member functions:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;///   hash(self, K) u64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;///   eql(self, K, K) bool
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// Adapted variants of many functions are provided.  These variants
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// take a pseudo key instead of a key.  Their context must have the functions:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;///   hash(self, PseudoKey) u64
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;///   eql(self, PseudoKey, K) bool
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; HashMap(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; K: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; V: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; Context: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; max_load_percentage: &lt;span style=&#34;font-weight:bold&#34;&gt;u64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OK, so the documentation of &lt;code&gt;std.hash_map.HashMap&lt;/code&gt; says that we can pass a &lt;code&gt;Context&lt;/code&gt; that has the &lt;code&gt;hash&lt;/code&gt; and &lt;code&gt;eql&lt;/code&gt; functions.
That should do it.&lt;/p&gt;
&lt;p&gt;Speaking of reusing the standard library - Zig already has the &amp;ldquo;FNV-1a&amp;rdquo; algorithm the book implements as a part of &lt;code&gt;std.hash.Fnv1a_32&lt;/code&gt;.
So we&amp;rsquo;re going to reuse it too.&lt;/p&gt;
&lt;p&gt;After walking through the chapter, here&amp;rsquo;s the final table:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; table_max_load = 75;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Table = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    hm: HashMap(*String, Value, Ctx, table_max_load),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Ctx = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; hash(_: Ctx, key: *String) &lt;span style=&#34;font-weight:bold&#34;&gt;u64&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(key.*.hash);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; eql(_: Ctx, key_a: *String, key_b: *String) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; key_a.*.hash == key_b.*.hash &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                std.mem.eql(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, key_a.*.bytes, key_b.*.bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; init(allocator: Allocator) Table {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Table{ .hm = HashMap(*String, Value, Ctx, table_max_load).init(allocator) };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; deinit(self: *Table) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.hm.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; findString(self: *Table, chars: str, hash: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) ?*String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.hm.getKey(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@constCast&lt;/span&gt;(&amp;amp;String{ .obj = &lt;span style=&#34;font-weight:bold&#34;&gt;undefined&lt;/span&gt;, .hash = hash, .bytes = chars }));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; set(self: *Table, key: *String, value: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.hm.fetchPut(key, value) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            common.exit(205, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;can&amp;#39;t put the key to a table&amp;#34;&lt;/span&gt;, .{})) |_|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// key is not new
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; get(self: *Table, key: *String) ?Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.hm.get(key);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; delete(self: *Table, key: *String) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.hm.remove(key);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Someone would say that that&amp;rsquo;s cheating.&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;While yes, I&#39;m not doing what the book suggests, I already have done that before.&lt;/summary&gt;
&lt;div class=&#34;details&#34;&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; table_max_load = 0.75;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Entry = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    key: ?*LoxObject,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    value: Value,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; growCapacity(capacity: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; ((capacity) &amp;lt; 8) 8 &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; capacity * 2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Table = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    entries: []Entry,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    capacity: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    allocator: Allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    count: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; init(allocator: Allocator) Table {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Table{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .allocator = allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .entries = &amp;amp;[_]Entry{},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .capacity = 0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .count = 0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; allocatedSlice(self: *Table) []Entry {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.entries.ptr[0..self.capacity];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; deinit(self: *Table) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.allocator.free(self.allocatedSlice());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; findEntry(entries: []Entry, capacity: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, key: *LoxObject) *Entry {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; hash = &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (key.data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .String =&amp;gt; |s| s.hash,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; index = hash % capacity;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; tombstone: ?*Entry = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; entry = &amp;amp;entries[index];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.key == &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.value.isNil()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (tombstone) |t| t &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; entry;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (tombstone == &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;) tombstone = entry;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.key == key) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; entry;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            index = (index + 1) % capacity;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; findString(self: *Table, chars: []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, hash: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) ?*LoxObject {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.count == 0) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; index = hash % self.capacity;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; entries = self.entries;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; entry = entries[index];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.key) |k| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (k.data) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    .String =&amp;gt; |s| s.hash == hash &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        std.mem.eql(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, s.chars, chars),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; entry.key;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.value.isNil()) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            index = (index + 1) % self.capacity;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; adjustCapacity(self: *Table, capacity: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; new_memory = self.allocator.alloc(Entry, capacity) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            common.exit(48, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;can&amp;#39;t allocate memory for the hash table&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (new_memory) |*entry| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            entry.key = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            entry.value = Nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.count = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (self.entries) |*entry| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.key) |key| {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; dest = findEntry(new_memory, capacity, key);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                dest.key = entry.key;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                dest.value = entry.value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                self.count += 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.allocator.free(self.allocatedSlice());
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.entries = new_memory;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.capacity = capacity;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; tableAddAll(from: *Table, to: *Table) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; i = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (i &amp;lt; from.capacity) : (i += 1) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; entry = &amp;amp;from.entries[i];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.key != &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                to.tableSet(entry.key, entry.value);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; set(self: *Table, key: *LoxObject, value: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.count + 1 &amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@floatToInt&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intToFloat&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;f32&lt;/span&gt;, self.capacity) * table_max_load)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; capacity = growCapacity(self.capacity);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.adjustCapacity(capacity);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; entry = findEntry(self.entries, self.capacity, key);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; is_new = entry.key == &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (is_new &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; entry.value.isNil()) self.count += 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        entry.key = key;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        entry.value = value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; is_new;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; get(self: *Table, key: *LoxObject) ?Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.count == 0) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; entry = findEntry(self.entries, self.capacity, key);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.key == &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; entry.value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; delete(self: *Table, key: *LoxObject) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.count == 0) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; entry = findEntry(self.entries, self.capacity, key);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (entry.key == &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        entry.key = &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        entry.value = True;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;/details&gt;
&lt;p&gt;I just don&amp;rsquo;t feel like doing it again.&lt;/p&gt;
&lt;p&gt;And, I would like to learn how to use Zig&amp;rsquo;s own hash tables, so this is a perfect opportunity.
The use of &lt;code&gt;Context&lt;/code&gt; is interesting - thanks to it we can implement the hashing however we want.&lt;/p&gt;
&lt;p&gt;The only thing I don&amp;rsquo;t like in the new solution is the &lt;code&gt;@constCast&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; findString(self: *Table, chars: str, hash: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) ?*String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.hm.getKey(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@constCast&lt;/span&gt;(&amp;amp;String{ .obj = &lt;span style=&#34;font-weight:bold&#34;&gt;undefined&lt;/span&gt;, .hash = hash, .bytes = chars }));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This function itself is a bit hacky, as we only mimic the key object by creating it on a stack.
Alternatively, I could use the &lt;code&gt;getKeyAdapted&lt;/code&gt;, and provide it a context that does a lookup of a fake key:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;17
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;18
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;19
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;20
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;21
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;22
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;23
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;24
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;25
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;26
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;27
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;28
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;29
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;30
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;31
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;32
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;33
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;34
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;35
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// after &amp;#39;const Ctx = struct { ... };&amp;#39;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; AdaptedCtx = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        h: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        b: str,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; init(b: str, h: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) AdaptedCtx {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; AdaptedCtx{ .b = b, .h = h };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; hash(self: AdaptedCtx, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; _: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;)) &lt;span style=&#34;font-weight:bold&#34;&gt;u64&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.h);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; eql(self: AdaptedCtx, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; _: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;), key: *String) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.h == key.*.hash &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                std.mem.eql(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, self.b, key.*.bytes);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now we can change &lt;code&gt;findString&lt;/code&gt; to:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;
&lt;table style=&#34;border-spacing:0;padding:0;margin:0;border:0;&#34;&gt;&lt;tr&gt;&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;43
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;44
&lt;/span&gt;&lt;span style=&#34;white-space:pre;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#7f7f7f&#34;&gt;45
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td style=&#34;vertical-align:top;padding:0;margin:0;border:0;;width:100%&#34;&gt;
&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; findString(self: *Table, chars: str, hash: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) ?*String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.hm.getKeyAdapted(&lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, AdaptedCtx.init(chars, hash));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;I don&amp;rsquo;t really like it either, and I don&amp;rsquo;t know which one is better/more idiomatic.
But, other than that, the new version is nice and clear.&lt;/p&gt;
&lt;h2 id=&#34;global-variables&#34;&gt;Global Variables&lt;/h2&gt;
&lt;p&gt;Here we go again.
By the end of this chapter, all tests will be broken.
Again.&lt;/p&gt;
&lt;p&gt;I mean, I&amp;rsquo;m glad I write tests, as Zig privies a test allocator that acts like &lt;a href=&#34;https://valgrind.org/&#34; target=&#34;_blank&#34;&gt;Valgrind&lt;/a&gt; and I had noticed a couple of memory leaks.
Not because the book has them, but just because I was careless and forgot to clean up some values.&lt;/p&gt;
&lt;p&gt;However, now no VM test is passing.
Why is that?
Because this chapter introduced statements, and now if you write any expression you must end it with a semicolon, thus turning it into a statement.
And statements are known for not returning anything.
Hence the &lt;code&gt;interpret&lt;/code&gt; function now can&amp;rsquo;t return anything, and therefore I can&amp;rsquo;t test for anything.
Amazing!&lt;/p&gt;
&lt;p&gt;Now, there are ways of working this around but all of these are hacky.
I think the proper solution would be to introduce a top-level &lt;code&gt;return&lt;/code&gt; statement, so we could return any expression from the top level.
And it&amp;rsquo;s a shame - the book mentions the REPL four times during this chapter, saying how useful something would be in the context of one.
However, it completely disregards the fact that REPL stands for Read Eval &lt;strong&gt;Print&lt;/strong&gt; Loop, and in our case, we can&amp;rsquo;t really print anything in the REPL, because now everything is a statement.
Welp.&lt;/p&gt;
&lt;p&gt;What I like about Lox is that the syntax for declaring a variable requires a keyword.
This is one of the reasons I dislike languages like Python - looking at the assignment you can&amp;rsquo;t guess if you&amp;rsquo;re creating a new variable or assigning an existing one.
Paired with the absence of scopes, we get this horrible thing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;foo&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;True&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        a = 10
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;print&lt;/span&gt;(a)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Why is &lt;code&gt;a&lt;/code&gt; available outside the scope of the &lt;code&gt;if&lt;/code&gt; statement?
Because there&amp;rsquo;s only one scope&lt;sup id=&#34;fnref:4&#34;&gt;&lt;a href=&#34;#fn:4&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;4&lt;/a&gt;&lt;/sup&gt; - the function scope.&lt;/p&gt;
&lt;p&gt;Lua is also guilty of this - assigning a non-existent variable creates a &lt;strong&gt;global&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;foo&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      a = 10
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   print(a)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;foo()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But at least it is global, and you can avoid this behavior by using a &lt;code&gt;local&lt;/code&gt; keyword.
Something that all of the Lua code should really do, that&amp;rsquo;s why Fennel uses &lt;code&gt;local&lt;/code&gt; by default.&lt;/p&gt;
&lt;p&gt;JavaScript also had this problem, but then they introduced the &lt;code&gt;let&lt;/code&gt; keyword.
It&amp;rsquo;s still weird because &lt;code&gt;let&lt;/code&gt; variables are &amp;ldquo;hoisted&amp;rdquo; - their logical position of definition is the top of their enclosing scope.
It&amp;rsquo;s not as bad as it sounds, e.g. you can&amp;rsquo;t do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;function&lt;/span&gt; f() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(x) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Error: can&amp;#39;t access lexical declaration &amp;#39;x&amp;#39; before initialization
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; x = 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But you can do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;function&lt;/span&gt; f() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;function&lt;/span&gt; g() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    console.log(x) &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// a closure? to what?
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; x = 1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  g()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;f() &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// prints 1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But I&amp;rsquo;m getting ahead of the book.
The next chapter is on local variables and scope, so let&amp;rsquo;s see how Lox handles them.&lt;/p&gt;
&lt;h2 id=&#34;local-variables&#34;&gt;Local Variables&lt;/h2&gt;
&lt;p&gt;And to be honest, it&amp;rsquo;s not bad.
Lox handles local variables pretty much the same way as most other languages I have used.
The only nitpick I have is this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; a = 20;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; a = 30; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Error at &amp;#39;a&amp;#39;: Already a variable with this name in this scope.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I don&amp;rsquo;t like this.
In Clojure, that&amp;rsquo;s the norm, because there&amp;rsquo;s no way to set a new value to an already established binding.
So you can overshadow it with a different value.&lt;/p&gt;
&lt;p&gt;Rust also allows shadowing, and I think that&amp;rsquo;s a good feature to have.
Sometimes you want to keep the name but change the type.
The Rust book has this &lt;a href=&#34;https://doc.rust-lang.org/stable/book/ch03-01-variables-and-mutability.html#shadowing&#34; target=&#34;_blank&#34;&gt;example&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; spaces = &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;   &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; spaces = spaces.len();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note, this can&amp;rsquo;t be done using mutability, because of the type system:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;mut&lt;/span&gt; spaces = &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;   &amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;spaces = spaces.len();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;The error says we’re not allowed to mutate a variable’s type:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ cargo run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   Compiling variables v0.1.0 (file:///projects/variables)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error[E0308]: mismatched types
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; --&amp;gt; src/main.rs:3:14
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2 |     let mut spaces = &amp;#34;   &amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  |                      ----- expected due to this value
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3 |     spaces = spaces.len();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  |              ^^^^^^^^^^^^ expected `&amp;amp;str`, found `usize`
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;For more information about this error, try `rustc --explain E0308`.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;error: could not compile `variables` due to previous error
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lox, however, is dynamically typed, so this can be done using mutability, and that may be a reason to disallow overshadowing.
Still, I would prefer variables that are constant, and overshadowing instead of assignments.&lt;/p&gt;
&lt;h2 id=&#34;jumping-back-and-forth&#34;&gt;Jumping Back and Forth&lt;/h2&gt;
&lt;p&gt;Oh, boy.&lt;/p&gt;
&lt;p&gt;This is a big chapter.
It introduces most of the control flow primitives to the language, in terms of branching, looping, and short-circuiting.
I have a lot to say.&lt;/p&gt;
&lt;h3 id=&#34;if-statements&#34;&gt;If statements&lt;/h3&gt;
&lt;p&gt;First things first, the book introduces the &lt;code&gt;if&lt;/code&gt; statement.
To which I ask - why not introduce an &lt;code&gt;if&lt;/code&gt; expression instead?
&lt;code&gt;if&lt;/code&gt; expressions are very useful, and not that hard to implement, especially in a small language like Lox.
I guess, it&amp;rsquo;s a bit late to do so, as almost everything in Lox grammar builds from the &lt;code&gt;statement&lt;/code&gt; rule, so &lt;code&gt;if&lt;/code&gt; expressions would be out of place.
It&amp;rsquo;s a shame though, as a lot of people don&amp;rsquo;t even know that &lt;code&gt;if&lt;/code&gt; &lt;em&gt;can&lt;/em&gt; be an expression, without being a ternary operator &lt;code&gt;?:&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Anyway, the &lt;code&gt;if&lt;/code&gt; expression is implemented in an interesting way.
We parse the &lt;code&gt;if&lt;/code&gt; and the condition, and &lt;em&gt;emit&lt;/em&gt; a jump instruction.
Emitting is a bit special we also added a placeholder that we will later patch:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; emitJump(self: *Self, instruction: OPCode) &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(instruction));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(0xff);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(0xff);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.currentChunk().code.items.len)) - 2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;These two &lt;code&gt;emitByte&lt;/code&gt; calls with &lt;code&gt;0xff&lt;/code&gt; as an argument are exactly for that.&lt;/p&gt;
&lt;p&gt;After the &lt;code&gt;emitJump&lt;/code&gt; step, we parse a statement and then emit another jump instruction.
And right after that, we patch the original jump:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; ifStatement(self: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.LEFT_PAREN, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;(&amp;#39; after &amp;#39;if&amp;#39;.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.RIGHT_PAREN, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;)&amp;#39; after condition.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; thenJump = self.emitJump(.JumpIfFalse);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Pop));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.statement();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; elseJump = self.emitJump(.Jump);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.patchJump(thenJump);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Pop));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.match(.ELSE)) self.statement();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.patchJump(elseJump);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The same happens for the &lt;code&gt;elseJump&lt;/code&gt; at the end of the function, if the &lt;code&gt;else&lt;/code&gt; branch is present.&lt;/p&gt;
&lt;p&gt;So, how it works?
The &lt;code&gt;patchJump&lt;/code&gt; function looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; patchJump(self: *Self, offset: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// -2 to adjust for the bytecode for the jump offset itself.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; jump = self.currentChunk().code.items.len - offset - 2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (jump &amp;gt; std.math.maxInt(&lt;span style=&#34;font-weight:bold&#34;&gt;u16&lt;/span&gt;)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.error_(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Too much code to jump over.&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.currentChunk().code.items[offset] = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;((jump &amp;gt;&amp;gt; 8) &amp;amp; 0xff);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.currentChunk().code.items[offset + 1] = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(jump &amp;amp; 0xff);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Basically, we count how much code we generated by reading the statement after the condition, and patch in the address we need to jump to if the condition was &lt;code&gt;false&lt;/code&gt;.
It&amp;rsquo;s a clever trick.
Notice, the &lt;code&gt;if&lt;/code&gt; statement itself doesn&amp;rsquo;t know anything about scopes - all that is handled by calling the &lt;code&gt;expression&lt;/code&gt; function.
It will kinda be important later.&lt;/p&gt;
&lt;p&gt;Aside from not being an expression, I have no objections to implementing the &lt;code&gt;if&lt;/code&gt; statement this way.
Well, the limitation of &lt;code&gt;65535&lt;/code&gt; opcodes is a bit weird, but if you may remember, the book earlier suggested implementing ways to have more than 256 constants by introducing more instructions that know how to deal with that.
Here, we could also introduce a &lt;code&gt;LongJump&lt;/code&gt; and &lt;code&gt;LongJumpIfFalse&lt;/code&gt; instructions that would handle &lt;code&gt;4294967295&lt;/code&gt; opcodes instead if the body is longer than &lt;code&gt;65535&lt;/code&gt; opcodes.
But this complicates things, and previously it resulted in a lot of misunderstanding where I should and should not take care of such long instructions while I did a first run of the book.
So I won&amp;rsquo;t do it here.&lt;/p&gt;
&lt;p&gt;Now, then there&amp;rsquo;s a &amp;ldquo;Challenge&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In addition to &lt;code&gt;if&lt;/code&gt; statements, most C-family languages have a multi-way &lt;code&gt;switch&lt;/code&gt; statement.
Add one to clox.
The grammar is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   switchStmt     &lt;span style=&#34;&#34;&gt;→&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;switch&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt; expression &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{&amp;#34;&lt;/span&gt; switchCase* defaultCase? &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;}&amp;#34;&lt;/span&gt; ;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   switchCase     &lt;span style=&#34;&#34;&gt;→&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;case&amp;#34;&lt;/span&gt; expression &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt; statement* ;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   defaultCase    &lt;span style=&#34;&#34;&gt;→&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;:&amp;#34;&lt;/span&gt; statement* ;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To execute a &lt;code&gt;switch&lt;/code&gt; statement, first evaluate the parenthesized &lt;code&gt;switch&lt;/code&gt; value expression.
Then walk the cases.
For each case, evaluate its value expression.
If the case value is equal to the &lt;code&gt;switch&lt;/code&gt; value, execute the statements under the case and then exit the switch statement.
Otherwise, try the next case.
If no case matches and there is a &lt;code&gt;default&lt;/code&gt; clause, execute its statements.&lt;/p&gt;
&lt;p&gt;To keep things simpler, we’re omitting fallthrough and &lt;code&gt;break&lt;/code&gt; statements.
Each case automatically jumps to the end of the switch statement after its statements are done.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Uh, this isn&amp;rsquo;t how &lt;code&gt;switch&lt;/code&gt; is supposed to work.
The &lt;code&gt;swich&lt;/code&gt; statement is a constant dispatch, meaning cases aren&amp;rsquo;t tried in order, instead, the right one is picked based on the condition.
It can be done with a jump table, or by computing offsets at compile time, and allowing only integer switching and then jumping to the given branch.
That&amp;rsquo;s also a reason why C implements &lt;code&gt;break&lt;/code&gt;, without it the program will continue executing to the next label because labels don&amp;rsquo;t really exist in the program.
This allows for clever tricks like the &lt;a href=&#34;https://en.m.wikipedia.org/wiki/Duff%27s_device&#34; target=&#34;_blank&#34;&gt;Duff&amp;rsquo;s device&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;send(to, from, count)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;register&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;short&lt;/span&gt; *to, *from;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;register&lt;/span&gt; count;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;register&lt;/span&gt; n = (count + 7) / 8;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (count % 8) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; 0: &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt; { *to = *from++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; 7:      *to = *from++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; 6:      *to = *from++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; 5:      *to = *from++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; 4:      *to = *from++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; 3:      *to = *from++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; 2:      *to = *from++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; 1:      *to = *from++;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (--n &amp;gt; 0);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I do understand that the book tries to keep things easy, but this kind of &lt;code&gt;switch&lt;/code&gt; statement is a useless addition in my opinion.
If Lox had macros, such &lt;code&gt;switch&lt;/code&gt; could be easily implemented in terms of chained &lt;code&gt;if else&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;loops&#34;&gt;Loops&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m skipping over logical operators, as I don&amp;rsquo;t have anything to say about them - they&amp;rsquo;re OK.
Loops, however, are, again, weird.&lt;/p&gt;
&lt;p&gt;First, we have a &lt;code&gt;while&lt;/code&gt; loop, which is probably the only kind of loop any language needs if it doesn&amp;rsquo;t implement tail call elimination/optimization technique.
It is implemented in pretty much the same way as the &lt;code&gt;if&lt;/code&gt; statement, except we emit a &lt;code&gt;Loop&lt;/code&gt; instruction instead.
Again, the design is OK, it is very bare-bones and clean:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; emitLoop(self: *Self, loopStart: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Loop));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; offset = self.currentChunk().code.items.len - loopStart + 2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (offset &amp;gt; std.math.maxInt(&lt;span style=&#34;font-weight:bold&#34;&gt;u16&lt;/span&gt;)) self.error_(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Loop body too large.&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;((offset &amp;gt;&amp;gt; 8) &amp;amp; 0xff));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(offset &amp;amp; 0xff));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; whileStatement(self: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; loopStart: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.currentChunk().code.items.len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.LEFT_PAREN, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;(&amp;#39; after &amp;#39;while&amp;#39;.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.RIGHT_PAREN, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;)&amp;#39; after condition.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; exitJump = self.emitJump(.JumpIfFalse);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Pop));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.statement();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitLoop(loopStart);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.patchJump(exitJump);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Pop));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then, however, we have a &lt;code&gt;for&lt;/code&gt; loop.
Not only the implementation is much more involved, as it is implemented in terms of the &lt;code&gt;while&lt;/code&gt; loop, but it is also quite useless.
Why?
Because it is a plain old C-style numeric loop.
We already have &lt;code&gt;while&lt;/code&gt;, why do we need &lt;code&gt;for&lt;/code&gt;?
I mean, it&amp;rsquo;s not too hard to translate this into &lt;code&gt;while&lt;/code&gt; loop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; i = 0; i &amp;lt; 10; i = i + 1) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{ &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; i = 0; &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (i &amp;lt; 10) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  i = i + 1; } }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s about the same amount of code.
Yes, I&amp;rsquo;ve used weird formatting on the &lt;code&gt;while&lt;/code&gt; loop example, but only to show that the actual amount of code is about the same.
And that&amp;rsquo;s exactly what the book does in the implementation of the &lt;code&gt;for&lt;/code&gt; loop, except it&amp;rsquo;s this amount of code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; forStatement(self: *Self) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.beginScope();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.consume(.LEFT_PAREN, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;(&amp;#39; after &amp;#39;for&amp;#39;.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.match(.SEMICOLON)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// No initializer.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.match(.VAR)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.varDeclaration();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.expressionStatement();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; loopStart: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.currentChunk().code.items.len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; exitJump: &lt;span style=&#34;font-weight:bold&#34;&gt;i32&lt;/span&gt; = -1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!self.match(.SEMICOLON)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.consume(.SEMICOLON, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;;&amp;#39; after loop condition.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Jump out of the loop if the condition is false.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;            exitJump = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.emitJump(.JumpIfFalse));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Pop)); &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Condition.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!self.match(.RIGHT_PAREN)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; bodyJump = self.emitJump(.Jump);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; incrementStart: &lt;span style=&#34;font-weight:bold&#34;&gt;u32&lt;/span&gt; = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.currentChunk().code.items.len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.expression();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Pop));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.consume(.RIGHT_PAREN, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expect &amp;#39;)&amp;#39; after for clauses.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.emitLoop(loopStart);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            loopStart = incrementStart;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.patchJump(bodyJump);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.statement();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.emitLoop(loopStart);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (exitJump != -1) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.patchJump(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(exitJump));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.emitByte(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromEnum&lt;/span&gt;(OPCode.Pop)); &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Condition.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.endScope();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, if Lox had macros, the language could define &lt;code&gt;for&lt;/code&gt; in terms of while without all this code.
Macros are special because they allow your language to operate on your code. which may sound complicated, but in actuality is much easier than fiddling with this bytecode generation, as it is more high-level.
Here&amp;rsquo;s an example of a &lt;code&gt;for&lt;/code&gt; macro for Emacs Lisp:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-emacs-lisp&#34; data-lang=&#34;emacs-lisp&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defmacro&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;condition&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;&amp;amp;rest&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;body&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  `(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;let&lt;/span&gt; (,&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;while&lt;/span&gt; ,&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;condition&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;progn&lt;/span&gt; ,@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;body&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;setq&lt;/span&gt; ,(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;car&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt;) ,&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;step&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;macroexpand-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; &amp;#39;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 0) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 10) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;+&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;print&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; (let ((a 0))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;;   (while (&amp;lt; a 10)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;;     (progn (print a))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;;     (setq a (+ a 1))))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes, it will get more involved if we would like to support a clause without an initializer, or with no explicit step, but in general, manipulating your language with your language is more concise.
Again, I know why the book teaches it this way, and it is good to show that the &lt;code&gt;for&lt;/code&gt; loop can be implemented in terms of a &lt;code&gt;while&lt;/code&gt; loop, but here&amp;rsquo;s a second question - what the &lt;code&gt;for&lt;/code&gt; loop is for in Lox?&lt;/p&gt;
&lt;p&gt;There are no arrays in Lox, and you can&amp;rsquo;t index strings either.
The language will add objects later to teach how to implement object-oriented programming, but that&amp;rsquo;s a hard sell for me and doesn&amp;rsquo;t make &lt;code&gt;for&lt;/code&gt; more useful.
Because &lt;code&gt;for&lt;/code&gt; doesn&amp;rsquo;t support object traversal either.
Well, theoretically, we can implement the linked list using objects in Lox, and then traverse them using the &lt;code&gt;for&lt;/code&gt; loop like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; pair = ll.rest(); pair.tail != nil; pair = ll.rest()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; val = pair.head;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// do stuff
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But that&amp;rsquo;s not a great interface for linked lists either.&lt;/p&gt;
&lt;p&gt;OK, I am nitpicking here.
But wait, there&amp;rsquo;s one more thing - where&amp;rsquo;s a &lt;code&gt;break&lt;/code&gt; statement?
Oh, there&amp;rsquo;s another &amp;ldquo;Challenge&amp;rdquo;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;
&lt;p&gt;In jlox, we had a challenge to add support for break statements.
This time, let’s do continue:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   continueStmt   &lt;span style=&#34;&#34;&gt;→&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;continue&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;;&amp;#34;&lt;/span&gt; ;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A continue statement jumps directly to the top of the nearest enclosing loop, skipping the rest of the loop body.
Inside a for loop, a continue jumps to the increment clause, if there is one.
It’s a compile-time error to have a continue statement not enclosed in a loop.&lt;/p&gt;
&lt;p&gt;Make sure to think about scope.
What should happen to local variables declared inside the body of the loop or in blocks nested inside the loop when a continue is executed?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Wait, it&amp;rsquo;s not about implementing &lt;code&gt;break&lt;/code&gt;?
It&amp;rsquo;s about implementing &lt;code&gt;continue&lt;/code&gt;?!
Then, what happened to &lt;code&gt;break&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;break&lt;/code&gt; is completely omitted from &lt;code&gt;clox&lt;/code&gt;.
Well, it was a challenge in &lt;code&gt;jlox&lt;/code&gt;, and even back then I considered it to be a weird choice.
Loops without the &lt;code&gt;break&lt;/code&gt; statement are even more useless.
Again, you can overcome this by modifying the condition, but that&amp;rsquo;s extremely ugly.
The book has this example in the &amp;ldquo;Design Note&amp;rdquo; section:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; found = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; x = 0; x &amp;lt; xSize; x++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; y = 0; y &amp;lt; ySize; y++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; z = 0; z &amp;lt; zSize; z++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (matrix[x][y][z] == 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        printf(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;found&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        found = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (found) &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (found) &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;They suggest that this can be rewritten using &lt;code&gt;goto&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; x = 0; x &amp;lt; xSize; x++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; y = 0; y &amp;lt; ySize; y++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; z = 0; z &amp;lt; zSize; z++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (matrix[x][y][z] == 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        printf(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;found&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;goto&lt;/span&gt; done;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;done:
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Alternatively, this can be done like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; found = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; x = 0; !found &amp;amp;&amp;amp; x &amp;lt; xSize; x++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; y = 0; !found &amp;amp;&amp;amp; y &amp;lt; ySize; y++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; z = 0; !found &amp;amp;&amp;amp; z &amp;lt; zSize; z++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (matrix[x][y][z] == 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        printf(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;found&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        found = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each &lt;code&gt;for&lt;/code&gt; loop will stop once &lt;code&gt;found&lt;/code&gt; is set to true.
While works, this is clumsy when you need to do an &lt;em&gt;early&lt;/em&gt; &lt;code&gt;break&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; x = 0; !done &amp;amp;&amp;amp; x &amp;lt; 10; x++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (x == 7) &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// rest of the body sits here
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; done = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;int&lt;/span&gt; x = 0; !done &amp;amp;&amp;amp; x &amp;lt; 10; x++) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (x == 7) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    done = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// rest of the body has to be in the else clause
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While works, this isn&amp;rsquo;t particularly great.
I work with a language that has neither &lt;code&gt;break&lt;/code&gt; nor &lt;code&gt;continue&lt;/code&gt; - Fennel.
It doesn&amp;rsquo;t have an early &lt;code&gt;return&lt;/code&gt; either.
It works, however, because Fennel is a lisp-like language, even though it just compiles to Lua.
Its syntax is concise, and that allows us to write things with less indentation and nesting than in most other languages.
Still, sometimes it is clumsy to write a certain algorithm without an early &lt;code&gt;break&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&#34;continue-and-break&#34;&gt;&lt;code&gt;continue&lt;/code&gt; and &lt;code&gt;break&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m not going to implement &lt;code&gt;continue&lt;/code&gt;, I just don&amp;rsquo;t feel like it, and certainly haven&amp;rsquo;t seen &lt;code&gt;continue&lt;/code&gt; used in any of the code in ten years.
But let&amp;rsquo;s just think how we could do that.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; i = 0; i &amp;lt; 10; i = i + 1) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (i == 5) &lt;span style=&#34;font-weight:bold&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you may remember, this loop really compiles to this equivalent &lt;code&gt;while&lt;/code&gt; loop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; i = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (i &amp;lt; 10) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (i == 5) &lt;span style=&#34;font-weight:bold&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    i = i + 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, not quite - I lied to you.
In the bytecode this loops looks nothing like that, instead it is structured kinda like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; i = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  condition:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (i &amp;lt; 10)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;goto&lt;/span&gt; body:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  increment:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  i = i + 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;goto&lt;/span&gt; condition:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  body:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (i == 5) &lt;span style=&#34;font-weight:bold&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;goto&lt;/span&gt; increment:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Upon initialization, we create a &lt;code&gt;condition:&lt;/code&gt; label, followed by the &lt;code&gt;if&lt;/code&gt; statement.
If the &lt;code&gt;if&lt;/code&gt; clause is &lt;code&gt;true&lt;/code&gt; we &lt;code&gt;goto&lt;/code&gt; (or rather use the &lt;code&gt;JUMP&lt;/code&gt; instruction) to the &lt;code&gt;body:&lt;/code&gt; label.
Then, at the end of the body, we &lt;code&gt;goto&lt;/code&gt; to the &lt;code&gt;increment:&lt;/code&gt; label, which finally brings us back to the &lt;code&gt;condition:&lt;/code&gt; label.&lt;/p&gt;
&lt;p&gt;Convoluted, huh?
Well, the VM doesn&amp;rsquo;t really have a &lt;code&gt;goto&lt;/code&gt;, instead it uses the jumping instructions, but the idea is the same.
Now we need to somehow incorporate &lt;code&gt;continue&lt;/code&gt; in that.&lt;/p&gt;
&lt;p&gt;Semantically, &lt;code&gt;continue&lt;/code&gt; should just go to the &lt;code&gt;increment:&lt;/code&gt; label, right?
Well, yes, however, consider this loop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; i = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (i &amp;lt; 10) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (i == 5) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; random = random_int(10);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// assume we can concatenate strings with numbers using +
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;      print &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;The loop will continue from&amp;#34;&lt;/span&gt; + random;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      i = random - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;continue&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print i;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    i = i + 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, this is no different, we still can jump to the &lt;code&gt;increment:&lt;/code&gt; label, but what happens to the &lt;code&gt;random&lt;/code&gt; variable?
Correct, it leaks because by jumping we don&amp;rsquo;t properly close the scope.
So, we need to track how much scopes we jump over as well.&lt;/p&gt;
&lt;p&gt;And, mind that, &lt;code&gt;continue&lt;/code&gt; may not be the last expression in the scope, so we can&amp;rsquo;t simply close the scope on it.
It can be nested in multiple scopes too.&lt;/p&gt;
&lt;p&gt;Implementing &lt;code&gt;break&lt;/code&gt; is even harder, because it has to jump over the loop, but we can&amp;rsquo;t know the loop size, because our compiler is single-pass.
Storing the marker and patching it later made harder because &lt;code&gt;break&lt;/code&gt; is part of the expression inside the &lt;code&gt;loop&lt;/code&gt;, and so we need to have a stack of &lt;code&gt;break&lt;/code&gt; labels somewhere.&lt;/p&gt;
&lt;p&gt;On the first run I tried some approaches, but failed.
None of my solutions worked, and I honestly don&amp;rsquo;t know why.
I consider this partly a book&amp;rsquo;s failure - implementing &lt;code&gt;break&lt;/code&gt; and &lt;code&gt;continue&lt;/code&gt; is non-trivial, and just throwing it as a &amp;ldquo;Challenge&amp;rdquo; is cheap.
I&amp;rsquo;ve searched for different implementations of the Lox on the web, and I can&amp;rsquo;t remember if I found any with the &lt;code&gt;continue&lt;/code&gt; statement implemented.
Maybe, that&amp;rsquo;s because &lt;code&gt;continue&lt;/code&gt; is pretty much useless.
Maybe, because it&amp;rsquo;s hard and unclear how to do so.&lt;/p&gt;
&lt;p&gt;I would appreciate if the book had two versions of CLox implemented - one is a bare minimum by-the-book, the other one with all challenges completed.
I wonder, if this would change the contents of the book, because when I did the challenges, a lot of later material became less clear, because the code differed a lot by that time.
Anyhow, there&amp;rsquo;s the third &amp;ldquo;Challenge&amp;rdquo; wich would be interesting to see implemented &lt;em&gt;officially&lt;/em&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;Control flow constructs have been mostly unchanged since Algol 68.
Language evolution since then has focused on making code more declarative and high level, so imperative control flow hasn’t gotten much attention.&lt;/p&gt;
&lt;p&gt;For fun, try to invent a useful novel control flow feature for Lox.
It can be a refinement of an existing form or something entirely new.
In practice, it’s hard to come up with something useful enough at this low expressiveness level to outweigh the cost of forcing a user to learn an unfamiliar notation and behavior, but it’s a good chance to practice your design skills.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;What&amp;rsquo;s the point of this &amp;ldquo;Challenge&amp;rdquo;?
I don&amp;rsquo;t know - maybe you would came up with something like &lt;a href=&#34;https://en.wikipedia.org/wiki/COMEFROM&#34; target=&#34;_blank&#34;&gt;&lt;code&gt;COMEFROM&lt;/code&gt;&lt;/a&gt;, or maybe you&amp;rsquo;ll be able to create something that will change computing forever.
I don&amp;rsquo;t want to waste time on pretty much useless stuff though.
If it&amp;rsquo;s meant to be a joke, then OK, but I didn&amp;rsquo;t get it.&lt;/p&gt;
&lt;h2 id=&#34;calls-and-functions&#34;&gt;Calls and Functions&lt;/h2&gt;
&lt;p&gt;Finally, some real action.
Defining functions is pretty straightforward, and I don&amp;rsquo;t really have anything to say about this chapter&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;EXCEPT&lt;/strong&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We’re not totally done, though.
The new return statement gives us a new compile error to worry about.
Returns are useful for returning from functions but the top level of a Lox program is imperative code too.
You shouldn’t be able to return from there.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;What?!&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We’ve specified that it’s a compile error to have a return statement outside of any function, which we implement like so:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;returnStatement&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;compiler.c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;in returnStatement()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (current-&amp;gt;type == TYPE_SCRIPT) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    error(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Can&amp;#39;t return from top-level code.&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (match(TOKEN_SEMICOLON)) {
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is one of the reasons we added that FunctionType enum to the compiler.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Why?
I mean, even the book kinda mentions that it can be useful:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Allowing return at the top level isn’t the worst idea in the world.
It would give you a natural way to terminate a script early.
You could maybe even use a returned number to indicate the process’s exit code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The author seems to be familiar with Lua, so I don&amp;rsquo;t really get why they discard top-level = return statements.
In my implementation, I left this check out.
Especially because it helps with making testing possible again.&lt;/p&gt;
&lt;p&gt;As for performance&amp;hellip;
Well, the book mentions that the current by-the-book implementation of CLox is faster than Python at computing the factorial of a number:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; fun fib(n) { if (n &amp;lt; 2) return n; return fib(n - 2) + fib(n - 1); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; var start = clock(); print fib(35); print clock() - start;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9.22746e+06
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.35232
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I&amp;rsquo;ve checked this Python implementation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Python 3.11.5 (main, Aug 28 2023, 00:00:00) [GCC 13.2.1 20230728 (Red Hat 13.2.1-1)] on linux
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Type &amp;#34;help&amp;#34;, &amp;#34;copyright&amp;#34;, &amp;#34;credits&amp;#34; or &amp;#34;license&amp;#34; for more information.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; def fib(n):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      if (n &amp;lt; 2):
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        return n;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      return fib(n - 2) + fib(n - 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;... ... ... ...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; import time
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt;&amp;gt;&amp;gt; start = time.time(); print(fib(35)); print(time.time() - start)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9227465
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.7716176509857178
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is certainly slower than CLox, what about my implementation in Zig?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./target/zig/bin/lox-0.1.73
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; fun fib(n) { if (n &amp;lt; 2) return n; return fib(n - 2) + fib(n - 1); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; var start = clock(); print fib(35); print clock() - start;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9227465
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;28.784000158309937
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Almost 30 seconds?!
I&amp;rsquo;m not even sure where the problem is, the speed difference is drastic.
And I&amp;rsquo;m unsure how to diagnose this too, perhaps there&amp;rsquo;s a way to profile Zig code?
Apparently, there&amp;rsquo;s &lt;a href=&#34;https://github.com/wolfpld/tracy&#34; target=&#34;_blank&#34;&gt;this project&lt;/a&gt;, and there are &lt;a href=&#34;https://github.com/nektro/zig-tracy&#34; target=&#34;_blank&#34;&gt;bindings available&lt;/a&gt;, but I couldn&amp;rsquo;t make it build.&lt;/p&gt;
&lt;p&gt;Wait&amp;hellip;
Zig does all these safety checks by default, right?
And the default optimization target is &amp;ldquo;Debug&amp;rdquo;.
Let&amp;rsquo;s try compiling with other optimization levels:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf ./target
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zig build -Doptimize=ReleaseSafe -p ./target/zig --cache-dir ./target/zig/.cache
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./target/zig/bin/lox-0.1.73
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; fun fib(n) { if (n &amp;lt; 2) return n; return fib(n - 2) + fib(n - 1); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; var start = clock(); print fib(35); print clock() - start;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9227465
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3.015000104904175
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;OK, &lt;code&gt;ReleaseSafe&lt;/code&gt; is ten times faster!
Let&amp;rsquo;s try &lt;code&gt;ReleaseFast&lt;/code&gt; then:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;rm -rf ./target
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zig build -Doptimize=ReleaseFast -p ./target/zig --cache-dir ./target/zig/.cache
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;./target/zig/bin/lox-0.1.73
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; fun fib(n) { if (n &amp;lt; 2) return n; return fib(n - 2) + fib(n - 1); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; var start = clock(); print fib(35); print clock() - start;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9227465
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.7879998683929443
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we&amp;rsquo;re as fast as Python, yay&amp;hellip;
Let&amp;rsquo;s throw in Lua for comparison:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Lua 5.4.4  Copyright (C) 1994-2022 Lua.org, PUC-Rio
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; function fib(n) if (n &amp;lt; 2) then return n end return fib(n - 2) + fib(n - 1) end
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; socket = require&amp;#34;socket&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; time = socket.gettime
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; start = time(); print(fib(35)); print(time() - start)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9227465
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.0116229057312
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, Lua is often called one of the fastest scripting languages, so I guess that statement holds up well.
A complete CLox implementation by the author of the book is also fast:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; fun fib(n) { if (n &amp;lt; 2) return n; return fib(n - 2) + fib(n - 1); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;gt; var start = clock(); print fib(35); print clock() - start;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9.22746e+06
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.3271
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, the way the result is printed isn&amp;rsquo;t particularly helpful.&lt;/p&gt;
&lt;p&gt;Well, now, that is sorted out, I think we can conclude that the implementation is fast enough.
I will keep the debug optimization target for now, as all these checks are helpful, but I guess I need a separate &lt;code&gt;make&lt;/code&gt; rule for a release build.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s one &amp;ldquo;Challenge&amp;rdquo; in this chapter I&amp;rsquo;d like to tackle:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;Add some more native functions to do things you find useful.
Write some programs using those.
What did you add?
How do they affect the feel of the language and how practical it is?&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Here are two functions that I would consider useful.&lt;/p&gt;
&lt;p&gt;The first one is &lt;code&gt;length&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; lengthNative(n: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, args: [*]Value, vm: *VM) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (n &amp;gt; 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; s = args[0];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (s.isString())
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; .{ .OK = Value.from(s.asString().bytes.len) };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected a string as an argument.&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Simply put, it&amp;rsquo;s handy to be able to know the length of the string.
It&amp;rsquo;s not generic, because there are no other countable data structures in Lox.&lt;/p&gt;
&lt;p&gt;As you may noticed, the return value of this function is not of a &lt;code&gt;Value&lt;/code&gt; type but an &lt;code&gt;Result&lt;/code&gt; one.
That&amp;rsquo;s because we have to signal a runtime error if we get something unexpected as an argument.
It plays nicely with the previous Challenge:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;
&lt;p&gt;Right now, there’s no way for a native function to signal a runtime error.
In a real implementation, this is something we’d need to support because native functions live in the statically typed world of C but are called from dynamically typed Lox land.
If a user, say, tries to pass a string to sqrt(), that native function needs to report a runtime error.&lt;/p&gt;
&lt;p&gt;Extend the native function system to support that.
How does this capability affect the performance of native calls?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;As for performance - we&amp;rsquo;re wrapping the result, and Zig is quite good at unwrapping these with the &lt;code&gt;switch&lt;/code&gt; statement.
Here&amp;rsquo;s how we handle native calls now:&lt;/p&gt;
&lt;p&gt;The other one is &lt;code&gt;tostring&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; tostringNative(nargs: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, args: [*]Value, vm: *VM) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (nargs == 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected an argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; array_list = std.ArrayList(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;).init(vm.allocator);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;defer&lt;/span&gt; array_list.deinit();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    args[0].format(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;, .{}, array_list.writer()) &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        common.exit(200, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OOME: can&amp;#39;t tostring a value&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; s = array_list.toOwnedSlice() &lt;span style=&#34;font-weight:bold&#34;&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        common.exit(200, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OOME: can&amp;#39;t tostring a value&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;defer&lt;/span&gt; vm.allocator.free(s);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; .{ .OK = (&lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; String.copy(vm, s)).obj.asValue() };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lox allows us to concatenate strings using the &lt;code&gt;+&lt;/code&gt; operator.
However, this is almost useless, because we can&amp;rsquo;t concatenate anything else to it.
Formatting a message is pretty much impossible.&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;tostring&lt;/code&gt; we can use &lt;code&gt;+&lt;/code&gt; with anything Lox supports:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; fun countdown(n) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          for (var i = n; i &amp;gt; 0; i = i - 1)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            print tostring(i) + &amp;#34;...&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          print &amp;#34;liftoff!!&amp;#34;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; countdown(3);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;liftoff!!
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I would also consider adding &lt;code&gt;sleep&lt;/code&gt; to the language, as this function is very useful when you need to wait, but don&amp;rsquo;t want to waste CPU.
However, Lox is more of a toy language, so having sleep in it isn&amp;rsquo;t necessary.
Anyway, here&amp;rsquo;s &lt;code&gt;sleep&lt;/code&gt; for completeness:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; sleepNative(nargs: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, args: [*]Value, vm: *VM) Result {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (nargs == 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected an argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; arg = args[0];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!arg.is(.Number))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected an integer argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; f = arg.asNumber();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; i: &lt;span style=&#34;font-weight:bold&#34;&gt;i64&lt;/span&gt; = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromFloat&lt;/span&gt;(f);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (f != &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@floatFromInt&lt;/span&gt;(i)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected an integer argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (i &amp;gt; 0) sleep(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(i * 1000000));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; .{.OK = Nil };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It doesn&amp;rsquo;t have much utility, though, but having both the &lt;code&gt;clock&lt;/code&gt; and &lt;code&gt;sleep&lt;/code&gt; functions can work wonders.&lt;/p&gt;
&lt;h2 id=&#34;closures&#34;&gt;Closures&lt;/h2&gt;
&lt;p&gt;This is getting out of hand - we&amp;rsquo;ve been adding new object types, and each one requires a method to test if it&amp;rsquo;s an instance of a particular object:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Obj = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    objType: Type,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    next: ?*Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isString(self: *Obj) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.objType == .String;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asString(self: *Obj) *String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@fieldParentPtr&lt;/span&gt;(String, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obj&amp;#34;&lt;/span&gt;, self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isFunction(self: *Obj) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.objType == .Function;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asFunction(self: *Obj) *Function {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@fieldParentPtr&lt;/span&gt;(Function, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obj&amp;#34;&lt;/span&gt;, self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isNativeFunction(self: *Obj) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.objType == .NativeFunction;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asNativeFunction(self: *Obj) *NativeFunction {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@fieldParentPtr&lt;/span&gt;(NativeFunction, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obj&amp;#34;&lt;/span&gt;, self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we need to add one more for &lt;code&gt;Closure&lt;/code&gt;, and then a bunch of others too.
You can see that the only difference between these methods is the enumeration tag or type.
So, instead of adding new ones, let&amp;rsquo;s delete all of these and use Zig&amp;rsquo;s &lt;code&gt;comptime&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Obj = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    objType: Type,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    next: ?*Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; is(self: *Obj, objType: Type) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.objType == objType;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; as(self: *Obj, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; T: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;) *T {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@fieldParentPtr&lt;/span&gt;(T, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obj&amp;#34;&lt;/span&gt;, self);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we only need to update all of our code from &lt;code&gt;x.isFunction()&lt;/code&gt; to &lt;code&gt;x.is(Function)&lt;/code&gt; which is a simple enough substitution.
Sadly, we can&amp;rsquo;t do the same for our evergrowing &lt;code&gt;Value&lt;/code&gt; struct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Number: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Bool: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Obj: *Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isNumber(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Number;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isBool(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Bool;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isObj(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It may seem that we can do the same, except use the enumeration literal as the parameter to &lt;code&gt;is&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; is(self: Value, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; target: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(.enum_literal)) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == target;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However, we also have methods like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isString(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Obj &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.Obj.objType == .String;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, here we can&amp;rsquo;t use this kind of signature.
We could do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; is(self: Value, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; target: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(.enum_literal), objType: ObjType) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; target == .Obj) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == target &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.Obj.objType == objType;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == target;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But then it would require us to write &lt;code&gt;x.is(.Number, undefined)&lt;/code&gt; and &lt;code&gt;y.is(.Obj, .String)&lt;/code&gt;, which is ugly.
So instead, we can do this &lt;code&gt;comptime&lt;/code&gt; check:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; is(self: Value, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; target: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(.enum_literal)) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@hasField&lt;/span&gt;(ObjType, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@tagName&lt;/span&gt;(target))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Obj &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.Obj.objType == target;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == target;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This way we can write both &lt;code&gt;x.is(.Number)&lt;/code&gt; and &lt;code&gt;y.is(.String)&lt;/code&gt; and it will generate an appropriate code at compile time.
This is as close as we can get to macros, I guess.
It gets harder from there, though.&lt;/p&gt;
&lt;p&gt;Now we need to get rid of these methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Number: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Bool: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Obj: *Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asNumber(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Number;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asBool(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Bool;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asObj(self: Value) *Obj {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Obj;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asString(self: Value) *String {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Obj.as(String);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asFunction(self: Value) *Function {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Obj.as(Function);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asNativeFunction(self: Value) *NativeFunction {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Obj.as(NativeFunction);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;As you can see, we again have two kinds of actions to perform - one is to return the desired enumeration tag value, and the other is to call a method.
The first few are easy to convert by using the same trick with &lt;code&gt;comptime target: @TypeOf(.enum_literal)&lt;/code&gt; but we can&amp;rsquo;t do the same for the last few, because &lt;code&gt;Obj.as&lt;/code&gt; expects a &lt;code&gt;type&lt;/code&gt;.
On the other hand, we know all of the types we&amp;rsquo;re gonna use with &lt;code&gt;as&lt;/code&gt;, so we can do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Number: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Bool: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Obj: *Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; typeNameUnqualified(&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; T: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;) []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; name = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeName&lt;/span&gt;(T);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; name[&lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (std.mem.lastIndexOfAny(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, name, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;)) |i| i + 1 &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; 0..];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; as(self: Value, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; T: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;) T {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@hasField&lt;/span&gt;(ObjType, typeNameUnqualified(T)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            self.Obj.as(&lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeInfo&lt;/span&gt;(T)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Pointer =&amp;gt; |p| p.child,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; T,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (T) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt; =&amp;gt; self.Number,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; =&amp;gt; self.Bool,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; =&amp;gt; self.Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            *Obj =&amp;gt; self.Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Not pretty, eh?
Well, that&amp;rsquo;s what you get, when you don&amp;rsquo;t have macros that operate on actual code.&lt;/p&gt;
&lt;p&gt;We call this function for basic types like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a.as(&lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;); &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Value{.Number=42} =&amp;gt; 42
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Transforming the &lt;code&gt;Value&lt;/code&gt; into an actual number.
And for object types, we do it like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// s is a `Value{.Obj=&amp;amp;{objType=.String,next=null}}`
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;s.as(*String); &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// =&amp;gt; &amp;amp;String{.Obj={objType=.String,next=null},.hash=1337,.bytes=&amp;#34;ваыв&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Because we want a pointer to the &lt;code&gt;String&lt;/code&gt; type we pass it as &lt;code&gt;*String&lt;/code&gt;.
Seems logical, but there&amp;rsquo;s a problem.&lt;/p&gt;
&lt;p&gt;First, we need to check if the &lt;code&gt;ObjType&lt;/code&gt; enum has the &lt;code&gt;String&lt;/code&gt; &lt;strong&gt;field&lt;/strong&gt;, but here we have a type.
More than that, it is actually an &lt;code&gt;*src.object.String&lt;/code&gt; type, not just &lt;code&gt;String&lt;/code&gt;, so we need a way to transform this type into a tag name.
The &lt;code&gt;typeNameUnqualified&lt;/code&gt; function takes care of it, but then there&amp;rsquo;s another problem - we need to pass the correct type to the &lt;code&gt;Object.as&lt;/code&gt; method, and &lt;code&gt;*String&lt;/code&gt; is not a correct type - it needs a &lt;code&gt;String&lt;/code&gt;!
So we have to do a little dance with &lt;code&gt;@typeInfo&lt;/code&gt; and check that we got a &lt;code&gt;Pointer&lt;/code&gt; type, that has a &lt;code&gt;child&lt;/code&gt; field, containing the type we&amp;rsquo;re interested in.
Then we can pass it to the &lt;code&gt;as&lt;/code&gt; method of the object.&lt;/p&gt;
&lt;p&gt;Phew!
We&amp;rsquo;re almost done with the refactoring, the only thing left is to remove these methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Number: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Bool: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Obj: *Obj,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ..
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; fromNumber(x: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;) Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Value{ .Number = x };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; fromBool(x: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;) Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Value{ .Bool = x };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; fromObj(x: *Obj) Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Value{ .Obj = x };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Well, that&amp;rsquo;s easy:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; from(x: anytype) Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(x)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime_float&lt;/span&gt; =&amp;gt; Value{ .Number = x },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; =&amp;gt; Value{ .Bool = x },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; =&amp;gt; Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        *Obj =&amp;gt; Value{ .Obj = x },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can do &lt;code&gt;Value.from(12.3)&lt;/code&gt; and it will do it&amp;rsquo;s job smoothly.&lt;/p&gt;
&lt;p&gt;Look at the before and after:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|-----------------------------Before------------------------------------+----------------------------------------After----------------------------------------|
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {                                        | &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;union&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;enum&lt;/span&gt;) {                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    Number: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;,                                                       |     Number: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;,                                                                    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    Bool: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;,                                                        |     Bool: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;,                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    Nil,                                                               |     Nil,                                                                            |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    Obj: *Obj,                                                         |     Obj: *Obj,                                                                      |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...                                                             |     // ...                                                                          |
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isNumber(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {                         |     &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; is(self: Value, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; target: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(.enum_literal)) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {   |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Number;                                        |         &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@hasField&lt;/span&gt;(ObjType, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@tagName&lt;/span&gt;(target))) {                        |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |             &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Obj &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.Obj.objType == target;                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |         } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {                                                                    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; fromNumber(x: &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;) Value {                           |             &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == target;                                                  |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Value{ .Number = x };                                   |         }                                                                           |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |     }                                                                               |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asNumber(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt; {                          |     &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; typeNameUnqualified(&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; T: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;) []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt; {                           |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Number;                                            |         &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; name = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeName&lt;/span&gt;(T);                                                  |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |         &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; name[&lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (std.mem.lastIndexOfAny(&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, name, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;)) |i| i + 1 &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; 0..]; |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |     }                                                                               |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isBool(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {                           |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Bool;                                          |     &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; as(self: Value, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; T: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;) T {                             |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |         &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@hasField&lt;/span&gt;(ObjType, typeNameUnqualified(T)))             |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |             self.Obj.as(&lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeInfo&lt;/span&gt;(T)) {                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; fromBool(x: &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;) Value {                            |                 .Pointer =&amp;gt; |p| p.child,                                            |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Value{ .Bool = x };                                     |                 &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; T,                                                          |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |             })                                                                      |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |         &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (T) {                                                           |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asBool(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {                           |             &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt; =&amp;gt; self.Number,                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Bool;                                              |             &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; =&amp;gt; self.Bool,                                                      |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |             &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; =&amp;gt; self.Nil,                                                       |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |             *Obj =&amp;gt; self.Obj,                                                       |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isObj(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {                            |             &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,                                                    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Obj;                                           |         };                                                                          |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |     }                                                                               |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; fromObj(x: *Obj) Value {                             |     &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; from(x: anytype) Value {                                          |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Value{ .Obj = x };                                      |         &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(x)) {                                                |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |             &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime_float&lt;/span&gt; =&amp;gt; Value{ .Number = x },                            |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |             &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; =&amp;gt; Value{ .Bool = x },                                             |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asObj(self: Value) *Obj {                            |             &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; =&amp;gt; Nil,                                                            |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Obj;                                               |             *Obj =&amp;gt; Value{ .Obj = x },                                              |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |             &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,                                                    |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |         };                                                                          |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isString(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {                         |     }                                                                               |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Obj &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.Obj.objType == .String;           | };                                                                                  |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asString(self: Value) *String {                      |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Obj.asString();                                    |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isFunction(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {                       |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Obj &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.Obj.objType == .Function;         |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asFunction(self: Value) *Function {                  |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Obj.asFunction();                                  |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isNativeFunction(self: Value) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {                 |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self == .Obj &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; self.Obj.objType == .NativeFunction;   |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|                                                                       |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; asNativeFunction(self: Value) *NativeFunction {      |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.Obj.asNativeFunction();                            |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|    }                                                                  |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|};                                                                     |                                                                                     |
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;|-----------------------------------------------------------------------+-------------------------------------------------------------------------------------|
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I guess, you can do many things that are done with macros in C using the comptime in Zig, although mostly when it is related to types.
Can&amp;rsquo;t say that I like this more than macros, but it gets the job done.
Now we can start this chapter proper!&lt;/p&gt;
&lt;p&gt;In the last chapter, we added functions and had them working, but you can do with just functions only so much.
In this chapter, we&amp;rsquo;re adding closures, which take our functions to a whole other level.&lt;/p&gt;
&lt;p&gt;Honestly, this chapter, while having mostly straightforward stuff, gave me a lot of trouble.
You see, there&amp;rsquo;s a certain problem with how the book gives you the material.
It&amp;rsquo;s subtle, but when the time comes it&amp;rsquo;s hard to ignore.&lt;/p&gt;
&lt;p&gt;The book gives you information bit by bit while trying to have a working interpreter at all times.
Yes, each chapter breaks the interpreter in the beginning, but by the end, you have something that works.
And often the chapter progressively gives you more examples and explains why they should work and why they don&amp;rsquo;t right now.
On its own, it&amp;rsquo;s a great way to show you your progress, but on the other hand, if a small mistake sneaks somewhere in the process, you won&amp;rsquo;t know till much later.
That&amp;rsquo;s exactly what happened to me.&lt;/p&gt;
&lt;p&gt;So, during this chapter, I tried most examples the book featured, and all of them seemed to work.
Satisfied, I proceeded to the &amp;ldquo;Challenges&amp;rdquo; section, and because I despise OOP much more than said &amp;ldquo;Challenges&amp;rdquo;, I decided to do this particular one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;a href=&#34;http://wiki.c2.com/?ClosuresAndObjectsAreEquivalent&#34; target=&#34;_blank&#34;&gt;famous koan&lt;/a&gt; teaches us that &amp;ldquo;objects are a poor man’s closure&amp;rdquo; (and vice versa).
Our VM doesn&amp;rsquo;t support objects yet, but now that we have closures we can approximate them.
Using closures, write a Lox program that models two-dimensional vector &amp;ldquo;objects&amp;rdquo;.
It should:
&lt;ul&gt;
&lt;li&gt;Define a &amp;ldquo;constructor&amp;rdquo; function to create a new vector with the given x and y coordinates.&lt;/li&gt;
&lt;li&gt;Provide &amp;ldquo;methods&amp;rdquo; to access the x and y coordinates of values returned from that constructor.&lt;/li&gt;
&lt;li&gt;Define an addition &amp;ldquo;method&amp;rdquo; that adds two vectors and produces a third.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;And it threw a weird error - it couldn&amp;rsquo;t find &lt;em&gt;some&lt;/em&gt; closures.&lt;/p&gt;
&lt;p&gt;Now, because Lox doesn&amp;rsquo;t have any data structures except for strings yet, I decided to implement a linked list, as closures are a perfect solution for that.
You don&amp;rsquo;t need any kind of data structures for linked lists as long as your language has closures.
Observe:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fun cons(head, tail) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fun cell(isHead) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (isHead)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; head;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; tail;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; cell;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fun first(cell) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; cell(&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fun rest(cell) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; cell(&lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With these three functions, we should be able to create a list like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; list = cons(1, cons(2, cons(3, nil)));
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And we should be able to traverse it with &lt;code&gt;for&lt;/code&gt; loop, albeit in a bit ugly way:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; head = list; head != nil; head = rest(head)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	print first(head);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now, if we try to execute this script, we get&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ ziglox list.lox
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Undefined variable &amp;#39;head&amp;#39;.
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[line 1] in cell
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[line 1] in first
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[line 1] in script
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Interpret Runtime Error
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;An error.
I then made sure that the &lt;code&gt;head&lt;/code&gt; variable is not related to the loop, by trying to get the head of the list with just &lt;code&gt;first(list)&lt;/code&gt;, but still got the same error.
Then I spent a day looking for what I did wrong.&lt;/p&gt;
&lt;p&gt;During this, I decided to try out all of the examples in the chapter.
I remember that all of them have worked before, and if they are then the problem is much deeper than the book accounts for.
So I started, and everything worked until I hit this one:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fun outer() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; x = &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;value&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fun middle() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fun inner() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      print x;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;create inner closure&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; inner;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  print &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;return from outer&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; middle;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; mid = outer();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; = mid();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Strangely enough, all later examples worked fine.
I&amp;rsquo;ll explain why in a moment.
For now, let it sink in - I had a working interpreter the whole time, and it could do everything the book suggested I try, yet there was a bug somewhere.&lt;/p&gt;
&lt;p&gt;So, here&amp;rsquo;s the thing.
For some reason, I decided to use a statically allocated stack for locals, back in the chapter where we added support for locals.
It worked well until we were introduced to the concept of compiler stacks.
However, Since I created the stack way back, I kept using it, and it basically meant that every compiler shared the same stack of locals.
So when we were searching for upvalues we saw the same upvalues on all levels.&lt;/p&gt;
&lt;p&gt;So you should now understand why it worked for all of the examples, except for the one above - it has one more compiler level.
After fixing this by using a proper dynamic array, all of the examples in this chapter work as expected.&lt;/p&gt;
&lt;p&gt;The linked list, however, still doesn&amp;rsquo;t work.
This time around, I decided that I would automate this process a bit, and put all of the examples as test cases.
I had to adjust them to actually return values instead of printing them, and what do you know - I found another broken case:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fun outer() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; a = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; b = 2;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fun middle() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; c = 3;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; d = 4;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    fun inner() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; a + c + b + d;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; inner;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; middle;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; outer()()();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It should return &lt;code&gt;10&lt;/code&gt;, but instead it returns &lt;code&gt;12&lt;/code&gt;.
How?
Well, if we print all of the values that went into the &lt;code&gt;inner&lt;/code&gt; function we&amp;rsquo;ll see that &lt;code&gt;a&lt;/code&gt; is &lt;code&gt;3&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt; is &lt;code&gt;2&lt;/code&gt;, &lt;code&gt;c&lt;/code&gt; is &lt;code&gt;2&lt;/code&gt;, and &lt;code&gt;d&lt;/code&gt; is &lt;code&gt;4&lt;/code&gt; and the answer changes to &lt;code&gt;14&lt;/code&gt;.
So while only the &lt;code&gt;d&lt;/code&gt; upvalue was correct, the introduction of &lt;code&gt;print&lt;/code&gt; still changed something.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s another bug.
And the same happens in my linked list implementation - &lt;code&gt;first&lt;/code&gt; returns itself.
Perhaps something to do with how we capture upvalues then?&lt;/p&gt;
&lt;p&gt;During these days of debugging, I tried everything I could - I moved &lt;code&gt;readByte&lt;/code&gt; to &lt;code&gt;CallFrame&lt;/code&gt; struct, I changed the instruction counter to the instruction pointer, as the book does, I also tried allocating stacks on the heap instead of the static memory.
I poked the reference implementation by Robert - the bytecode is exactly the same as in my implementation, so it has to be something in the VM.
I printed pointer addresses, analyzing if there is a different between my implementation and C, and comparing relative offsets - again, they&amp;rsquo;re the same.
Nothing helped.
Reverting to my previous implementation revealed that this case wasn&amp;rsquo;t handled properly as well - I somehow missed it back then too.&lt;/p&gt;
&lt;p&gt;And then I found it.
After 4 days of debugging the reason was that I &lt;strong&gt;SOMEHOW&lt;/strong&gt; missed this line in the &lt;code&gt;captureUpvalue&lt;/code&gt; function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;createdUpvalue.next = upvalue;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Finally, everything works:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// cons, first, rest...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; list = cons(1, cons(2, cons(3, nil)));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; head = list; head != nil; head = rest(head)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    print first(head);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And, guess what?
During all this debugging, and trying different things I managed to improve the speed of the interpreter a bit:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; fun fib(n) { &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (n &amp;lt; 2) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; n; &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; fib(n - 2) + fib(n - 1); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; s = clock(); print fib(35); print clock() - s;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9227465
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.4010000228881836
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s the same code when checked out to the previous commit at chapter 24:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; fun fib(n) { &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (n &amp;lt; 2) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; n; &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; fib(n - 2) + fib(n - 1); }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; s = clock(); print fib(35); print clock() - s;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;9227465
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.815000057220459
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nice!
Going back to the third &amp;ldquo;Challenge&amp;rdquo;, here&amp;rsquo;s my attempt at an object via closures:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;fun vec2(x, y) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; _x = x; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// storage
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; _y = y;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fun obtainer(what) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (what == &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; _x;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (what == &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; _y;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fun establisher(what, val) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (what == &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;) _x = val;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (what == &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt;) _y = val;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fun add(other) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; ox = other(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obtain&amp;#34;&lt;/span&gt;)(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; oy = other(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obtain&amp;#34;&lt;/span&gt;)(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _x = _x + ox;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    _y = _y + oy;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  fun clss (action) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (action == &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obtain&amp;#34;&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; obtainer;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (action == &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;establish&amp;#34;&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; establisher;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (action == &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;add&amp;#34;&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; add;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; clss;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; a = vec2(3, nil);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; b = vec2(22, 10);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;establish&amp;#34;&lt;/span&gt;)(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt;, 7);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;add&amp;#34;&lt;/span&gt;)(b);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print a(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obtain&amp;#34;&lt;/span&gt;)(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;x&amp;#34;&lt;/span&gt;) + a(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;obtain&amp;#34;&lt;/span&gt;)(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;y&amp;#34;&lt;/span&gt;); &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// 42
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It&amp;rsquo;s a &lt;code&gt;vec2&lt;/code&gt; structure representing this kind of data &lt;code&gt;{.x = 1, .y = 2}&lt;/code&gt;.
Although it&amp;rsquo;s a bit rough to use, it is a proper data structure.
And yes - I like &lt;code&gt;obtain&lt;/code&gt; and &lt;code&gt;establish&lt;/code&gt; better than &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;set&lt;/code&gt;.
What?&lt;/p&gt;
&lt;h2 id=&#34;garbage-collection&#34;&gt;Garbage Collection&lt;/h2&gt;
&lt;p&gt;Hooo&amp;hellip;&lt;/p&gt;
&lt;p&gt;Now we get to the interesting stuff.
The book implements this language in C, and C is pretty straightforward when it comes to memory management.
Well, straightforward might not be a proper word, but by default it&amp;rsquo;s quite basic - you have &lt;code&gt;malloc&lt;/code&gt;, &lt;code&gt;free&lt;/code&gt;, and &lt;code&gt;realloc&lt;/code&gt; as a base.&lt;/p&gt;
&lt;p&gt;Zig, on the other hand, doesn&amp;rsquo;t have a default allocator, which, in theory, should make it more appropriate for embedded systems, where there may not be any way to actually allocate memory.
This, in turn, affects the language design - every Zig function that wants to allocate some memory, accepts an allocator (or accesses it from an enclosing &lt;code&gt;struct&lt;/code&gt; if that&amp;rsquo;s a method).
Now you can understand why all of the code in this post had something like &lt;code&gt;Allocator&lt;/code&gt; in function arguments or structures.&lt;/p&gt;
&lt;p&gt;This meant that we didn&amp;rsquo;t have to implement most of the book&amp;rsquo;s &lt;code&gt;memory.c&lt;/code&gt; and &lt;code&gt;memory.h&lt;/code&gt; because Zig&amp;rsquo;s allocators already can do all of that.
However, now we can&amp;rsquo;t just use an existing allocator, as we need to implement garbage collection mid-allocation.
That&amp;rsquo;s why we need a custom allocator.&lt;/p&gt;
&lt;p&gt;Thankfully, we don&amp;rsquo;t really have to do the allocation ourselves.
Instead, we can create an allocator that just wraps another allocator, like a decorator.
All we need to do is to implement these three functions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; GCAllocator = &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    parentAllocator: Allocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    bytesAllocated: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; init(parentAllocator: Allocator) GCAllocator {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; .{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .parentAllocator = parentAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .bytesAllocated = 0,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; allocator(self: *GCAllocator) Allocator {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; .{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .ptr = self,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            .vtable = &amp;amp;.{ .alloc = alloc, .resize = resize, .free = free },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; alloc(ctx: *anyopaque, len: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, log2_ptr_align: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, ra: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;) ?[*]&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; self: *GCAllocator = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@ptrCast&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@alignCast&lt;/span&gt;(ctx));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; result = self.parentAllocator.rawAlloc(len, log2_ptr_align, ra);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (result != &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;) self.bytesAllocated += len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; result;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; resize(ctx: *anyopaque, buf: []&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, log2_buf_align: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, new_len: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, ra: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; self: *GCAllocator = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@ptrCast&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@alignCast&lt;/span&gt;(ctx));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.parentAllocator.rawResize(buf, log2_buf_align, new_len, ra)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (new_len &amp;lt;= buf.len) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                self.bytesAllocated -= buf.len - new_len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                self.bytesAllocated += new_len - buf.len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        std.debug.assert(new_len &amp;gt; buf.len);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; free(ctx: *anyopaque, buf: []&lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, log2_buf_align: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, ra: &lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;) &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; self: *GCAllocator = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@ptrCast&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@alignCast&lt;/span&gt;(ctx));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.parentAllocator.rawFree(buf, log2_buf_align, ra);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self.bytesAllocated -= buf.len;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we should be able to implement the rest of this chapter in terms of this allocator.
And, thanks to the fact that all our functions already accept an allocator, we can just plug this one in, and it should work!&lt;/p&gt;
&lt;p&gt;I called it &lt;code&gt;GCAllocator&lt;/code&gt;, although right now it is more like a &lt;em&gt;tracking&lt;/em&gt; allocator.
It tracks how many bytes were allocated and freed, and that&amp;rsquo;s basically it.
With that, we can implement the rest of the interface.&lt;/p&gt;
&lt;p&gt;The book suggests to implement the &amp;ldquo;Mark and Sweep&amp;rdquo; algorithm.
While not great, it is perfect for teaching.
Moreover, there&amp;rsquo;s still software that uses this technique, for example, one that I&amp;rsquo;m writing this blog in - Emacs!
It was always an active debate whether the GC in Emacs is outdated or not, but I can say that Emacs performs fine for my daily tasks, so it&amp;rsquo;s probably OK.
Something like JVM would never settle on something simple like this though.&lt;/p&gt;
&lt;p&gt;I won&amp;rsquo;t go into the source code of the collector itself, as the translation from C is pretty much 1:1 here.
One thing to point out though is the use of &lt;code&gt;grayStack&lt;/code&gt; in the VM.
The book uses an array of pointers to the objects, and we do the same by using &lt;code&gt;ArrayList(*Obj)&lt;/code&gt;.
However, using &lt;code&gt;append&lt;/code&gt; to add things to this array can throw an out-of-memory error.
So when we do the marking of objects we have to handle that.&lt;/p&gt;
&lt;p&gt;Between these two chapters, I&amp;rsquo;ve refactored the code to use Zig&amp;rsquo;s errors.
So handling allocation failures is simple enough now, but I don&amp;rsquo;t really know if we &lt;em&gt;should&lt;/em&gt; handle out-of-memory errors.
On one hand, JVM doesn&amp;rsquo;t recommend handling the OOME, and the most common practice I know of is to do a heap dump and die.
On the other hand, we&amp;rsquo;re dealing with OOME inside the virtual machine, not inside the language itself, as Lox doesn&amp;rsquo;t really have exceptions or other kinds of error handling.
I chose to kill the VM if the OOME ever occurs, but in a real language, I would probably not do it this way.
And I think in the language that runs on the VM it should be possible to handle OOM too.&lt;/p&gt;
&lt;h2 id=&#34;classes-and-instances&#34;&gt;Classes and Instances&lt;/h2&gt;
&lt;p&gt;Now, I&amp;rsquo;m a bit torn apart here.
I don&amp;rsquo;t want to implement classes.&lt;/p&gt;
&lt;p&gt;I mean, seriously, this language doesn&amp;rsquo;t have any data structures yet, and we&amp;rsquo;re already in classes?
Where are arrays, at the very least?
Plus, we already did classes in &lt;code&gt;cljlox&lt;/code&gt;, so it&amp;rsquo;s boring to do it again.&lt;/p&gt;
&lt;p&gt;Instead, I think it would be better to go the Lua route and give users only a basic set of data structures, like hash tables.
Except, actually give users data structure&lt;b&gt;s&lt;/b&gt;, and not a mixed table/array thingy.
I&amp;rsquo;m not sure, however, if it will affect the last chapter that talks about optimizations.&lt;/p&gt;
&lt;p&gt;Yet, there are benefits in the following chapters.
For example, if I were to introduce a hash table, accessing keys from it can be made with a special syntax like &lt;code&gt;a.b&lt;/code&gt;.
Assigning a value to the key can also use this syntax, and we&amp;rsquo;re going to handle it in the next chapter.&lt;/p&gt;
&lt;p&gt;I guess, classes are more involved, and thus a bit better fit for teaching how to make a language, but on the other hand, class systems can be a fully runtime thing.
Sparkle some macros on top of it, and you can hack your own object system in a weekend.
That&amp;rsquo;s what a lot of Lisp/Scheme projects did back in the day.&lt;/p&gt;
&lt;p&gt;Anyway, after adding the &lt;code&gt;Class&lt;/code&gt; opcode and some other stuff around it the book says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;There you have it, our VM supports classes now. You can run this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;class&lt;/span&gt; Brioche {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print Brioche;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Unfortunately, printing is about all you can do with classes, so next is making them more useful.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Unfortunately, we have classes before arrays.&lt;/p&gt;
&lt;p&gt;Yes, I&amp;rsquo;m negative, because come on, arrays are such a basic data structure that not having them is a bummer.
How would you implement anything without an array?
Well, technically, we can use our closure-based linked lists as a substitute, but it has horrible performance in many algorithms where constant indexing is required.&lt;/p&gt;
&lt;p&gt;Anyway, after implementing field access the chapter is suddenly over.
That&amp;rsquo;s it?
Well, right now it&amp;rsquo;s just a hash table with inconvenient syntax.
I mean, yes, classes are just a special case of a hash table in some languages, and hash tables are a special case of classes in some other &lt;em&gt;broken&lt;/em&gt; languages.
But here, why didn&amp;rsquo;t we introduce a basic hash table with an open set of keys, even though our runtime already supports one?&lt;/p&gt;
&lt;p&gt;Onto &amp;ldquo;Challenges&amp;rdquo;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Trying to access a non-existent field on an object immediately aborts the entire VM.
The user has no way to recover from this runtime error, nor is there any way to see if a field exists before trying to access it.
It’s up to the user to ensure on their own that only valid fields are read.&lt;/p&gt;
&lt;p&gt;How do other dynamically typed languages handle missing fields?
What do you think Lox should do?
Implement your solution.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Yeah, that was a strange decision.
I decided to just return &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;2&#34;&gt;
&lt;li&gt;Fields are accessed at runtime by their string name.
But that name must always appear directly in the source code as an identifier token.
A user program cannot imperatively build a string value and then use that as the name of a field.
Do you think they should be able to?
Devise a language feature that enables that and implement it.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, first of all, a user program cannot imperatively build a string value at all, because Lox has no string library.
A few chapters ago I added &lt;code&gt;tostring&lt;/code&gt; and with that, it is possible to build strings using &lt;code&gt;+&lt;/code&gt;, but not in vanilla Lox.&lt;/p&gt;
&lt;p&gt;A user should be able to do that, but most languages that allow that it does require a special syntax, and I don&amp;rsquo;t want to deal with that now.
If I did, though, I would probably introduce something like &lt;code&gt;foo[bar]&lt;/code&gt;, but instead we can always use a native function:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; getNative(nargs: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, args: [*]Value, vm: *VM) !Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (nargs == 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected an argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; instance = args[0];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!instance.is(.Instance))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected a class instance as the first argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; name = args[1];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!name.is(.String))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected a string as the second argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; instance.as(*Instance).fields.get(name.as(*String)) &lt;span style=&#34;font-weight:bold&#34;&gt;orelse&lt;/span&gt; Nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; setNative(nargs: &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;, args: [*]Value, vm: *VM) !Value {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (nargs == 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected an argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; instance = args[0];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!instance.is(.Instance))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected a class instance as the first argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; name = args[1];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (!name.is(.String))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; vm.runtimeError(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected a string as the second argument&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (nargs &amp;gt;= 3 &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; !args[2].is(.Nil)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; value = args[2];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _ = &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; instance.as(*Instance).fields.set(name.as(*String), value);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; value;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            _ = instance.as(*Instance).fields.delete(name.as(*String));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; Nil;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With these we can do &lt;code&gt;set(foo, &amp;quot;vaiv&amp;quot;, 42)&lt;/code&gt; and &lt;code&gt;get(foo, &amp;quot;vaiv&amp;quot;)&lt;/code&gt;.
These native functions are bloating the &lt;code&gt;VM&lt;/code&gt; struct, so I should probably move them out.&lt;/p&gt;
&lt;p&gt;As you can see, I don&amp;rsquo;t care if the native function has more arguments than it really needs.
The only thing I care about is the required arguments.
I like this design more, and in fact, doing things this way should allow variadic functions naturally.
Maybe I should implement them in the future, alongside arrays.&lt;/p&gt;
&lt;p&gt;Lastly:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;3&#34;&gt;
&lt;li&gt;Conversely, Lox offers no way to remove a field from an instance.
You can set a field’s value to nil, but the entry in the hash table is still there.
How do other languages handle this?
Choose and implement a strategy for Lox.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;But as you may have noticed, I already implemented this.
Setting a field to &lt;code&gt;nil&lt;/code&gt; removes it from the hash table.
This is how it works in Lua, and while I strongly dislike this particular part of Lua, I don&amp;rsquo;t have any problems with this in Lox.
Why?
Because Lua has a weird mix of tables and arrays, setting a value in the array to &lt;code&gt;nil&lt;/code&gt; also removes it from the array, as if the array were a hash table with integer keys.&lt;/p&gt;
&lt;p&gt;So by doing &lt;code&gt;arr[3] = nil&lt;/code&gt; you effectively transform &lt;code&gt;{&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;quot;d&amp;quot;}&lt;/code&gt; into &lt;code&gt;{1 = &amp;quot;a&amp;quot;, 2 = &amp;quot;b&amp;quot;, 4 = &amp;quot;d&amp;quot;}&lt;/code&gt;, or rather &lt;code&gt;{&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, 4 = &amp;quot;d&amp;quot;}&lt;/code&gt;, as Lua views it.
This breaks iteration on arrays, as no the iteration will only see the first two fields (and yes, arrays in Lua start from &lt;code&gt;1&lt;/code&gt;, which is great):&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-lua&#34; data-lang=&#34;lua&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arr = {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;a&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;b&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;c&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;d&amp;#34;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-- before set --&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; i,v &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; ipairs(arr) &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   print(i, v)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;arr[3] = &lt;span style=&#34;font-weight:bold&#34;&gt;nil&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-- after set --&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; i,v &lt;span style=&#34;font-weight:bold&#34;&gt;in&lt;/span&gt; ipairs(arr) &lt;span style=&#34;font-weight:bold&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   print(i, v)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-- before set --
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1	a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2	b
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3	c
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;4	d
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;-- after set --
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1	a
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2	b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If Lua did not remove things when you set them to &lt;code&gt;nil&lt;/code&gt; and instead provided a &lt;code&gt;contains&lt;/code&gt; and &lt;code&gt;remove&lt;/code&gt; functions to check for key presence, and removal of combined array/table would be fine, but in its current state, it&amp;rsquo;s too easy to trip on this.
I know that because I teach people how to write Lua, and this always makes people angry.&lt;/p&gt;
&lt;p&gt;If the language provides separate array and table objects, setting table keys to &lt;code&gt;nil&lt;/code&gt; for removal is fine - it should not matter if the key is present and &lt;code&gt;nil&lt;/code&gt; or just absent.
Arrays, however, should be able to have &lt;code&gt;nil&lt;/code&gt; in them, and removal is a whole different operation, that shifts all other elements, so setting array elements to &lt;code&gt;nil&lt;/code&gt; for removal doesn&amp;rsquo;t really make sense.
Anyway, that&amp;rsquo;s my reasoning behind this, I&amp;rsquo;m sure you can disagree, but it&amp;rsquo;s OK.&lt;/p&gt;
&lt;p&gt;Finally:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;
&lt;p&gt;Because fields are accessed by name at runtime, working with instance state is slow.
It’s technically a constant-time operation—thanks, hash tables—but the constant factors are relatively large.
This is a major component of why dynamic languages are slower than statically typed ones.&lt;/p&gt;
&lt;p&gt;How do sophisticated implementations of dynamically typed languages cope with and optimize this?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ah, if only we had arrays - we could easily implement records that have constant time access to fields by field index determined at compile time.
Alas.&lt;/p&gt;
&lt;h2 id=&#34;methods-and-initializers&#34;&gt;Methods and Initializers&lt;/h2&gt;
&lt;p&gt;I don&amp;rsquo;t have anything to say about this chapter.
Mostly, because it is straightforward and concise.&lt;/p&gt;
&lt;p&gt;Still, I would prefer not having methods at all, but there were interesting bits to tackle with &lt;code&gt;this&lt;/code&gt;, so I guess it was worth it.&lt;/p&gt;
&lt;h2 id=&#34;superclasses&#34;&gt;Superclasses&lt;/h2&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-c&#34; data-lang=&#34;c&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...return constantInstruction(&amp;#34;OP_CLASS&amp;#34;, chunk, offset);
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; OP_INHERIT:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; simpleInstruction(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;OP_INHERIT&amp;#34;&lt;/span&gt;, offset);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;//  case OP_METHOD: ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;em&gt;Simple instruction&lt;/em&gt;, how ironic.&lt;/p&gt;
&lt;p&gt;The chapter proceeds adding tons of new stuff in the compiler, and then in the VM.
While straightforward, I can&amp;rsquo;t help but notice how things got more complicated since we added classes.
Honestly, I have never seen a program where inheritance made things easier.&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;A tenet of object-oriented programming is that a class should ensure new objects are in a valid state.
In Lox, that means defining an initializer that populates the instance’s fields.
Inheritance complicates invariants because &amp;hellip;&lt;/p&gt;
&lt;p&gt;If Lox was your language, how would you address this, if at all?
If you would change the language, implement your change.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;If Lox was my language it wouldn&amp;rsquo;t have classes at all.
And it would have arrays.&lt;/p&gt;
&lt;h2 id=&#34;optimization&#34;&gt;Optimization&lt;/h2&gt;
&lt;p&gt;The final chapter.
Honestly, didn&amp;rsquo;t think that I&amp;rsquo;d make it through.
It&amp;rsquo;s 4 AM right now, as I&amp;rsquo;m writing this, and perhaps I should go to sleep, but I want to finish this stuff quicker, so&amp;hellip;&lt;/p&gt;
&lt;p&gt;The chapter starts with a benchmark:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;class&lt;/span&gt; Zoo {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  init() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.aardvark = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.baboon   = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.cat      = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.donkey   = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.elephant = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.fox      = 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ant()    { &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.aardvark; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  banana() { &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.baboon; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  tuna()   { &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.cat; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  hay()    { &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.donkey; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  grass()  { &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.elephant; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mouse()  { &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.fox; }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; zoo = Zoo();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; sum = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; start = clock();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (sum &amp;lt; 100000000) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  sum = sum + zoo.ant()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            + zoo.banana()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            + zoo.tuna()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            + zoo.hay()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            + zoo.grass()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            + zoo.mouse();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print clock() - start;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print sum;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Running this on the reference implementation takes &lt;code&gt;3.87092&lt;/code&gt; seconds and the result is &lt;code&gt;1e+08&lt;/code&gt; or &lt;code&gt;100000000&lt;/code&gt;.
Running on the release build of my language takes &lt;code&gt;8.065999984741211&lt;/code&gt;, and the result is &lt;code&gt;100000002&lt;/code&gt;.
Don&amp;rsquo;t mind the difference, it&amp;rsquo;s an IEEE 754 quirk - if we change how &lt;code&gt;clox&lt;/code&gt; prints it&amp;rsquo;s value from scientific notation to plain float, we&amp;rsquo;ll get the same thing.&lt;/p&gt;
&lt;p&gt;Now, my implementation is twice as slow.
Thankfully, the loop itself is fast - if we just do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; sum = 0;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; start = clock(); &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (sum &amp;lt; 100000000) { sum = sum + 1 + 1 + 1 + 1 + 1 + 1; } print clock() - start;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2.2915e+01
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;ziglox&amp;gt;  print sum;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1.00000002e+08
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;nil
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The speed is comparable.&lt;/p&gt;
&lt;p&gt;Unfortunately, I am lazy.
The book proceeds at optimizing table lookups, by using bit-masking instead of the modulo operator.
I&amp;rsquo;m not using the table implementation from the book itself - instead, I&amp;rsquo;m wrapping Zig&amp;rsquo;s &lt;code&gt;std.hash_map.HashMap&lt;/code&gt;.
Fortunately, Zig&amp;rsquo;s &lt;code&gt;HashMap&lt;/code&gt; already uses bit-masking:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// Find the index containing the data for the given key.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// Whether this function returns null is almost always
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// branched on after this function returns, and this function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// returns null/not null from separate code paths.  We
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// want the optimizer to remove that branch and instead directly
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// fuse the basic blocks after the branch to the basic blocks
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// from this function.  To encourage that, this function is
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;/// marked as inline.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; getIndex(self: Self, key: anytype, ctx: anytype) ?&lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; verifyContext(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(ctx), &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(key), K, Hash, &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.size == 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// If you get a compile error on this line, it means that your generic hash
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// function is invalid for these parameters.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; hash = ctx.hash(key);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// verifyContext can&amp;#39;t verify the return type of generic hash functions,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// so we need to double-check it here.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(hash) != Hash) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@compileError&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Context &amp;#34;&lt;/span&gt; ++ &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeName&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(ctx)) ++ &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; has a generic hash function that returns the wrong type! &amp;#34;&lt;/span&gt; ++ &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeName&lt;/span&gt;(Hash) ++ &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; was expected, but found &amp;#34;&lt;/span&gt; ++ &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeName&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(hash)));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; mask = self.capacity() - 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; fingerprint = Metadata.takeFingerprint(hash);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Don&amp;#39;t loop indefinitely when there are no empty slots.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; limit = self.capacity();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; idx = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@truncate&lt;/span&gt;(hash &amp;amp; mask));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;var&lt;/span&gt; metadata = self.metadata.? + idx;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt; (!metadata[0].isFree() &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; limit != 0) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (metadata[0].isUsed() &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; metadata[0].fingerprint == fingerprint) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; test_key = &amp;amp;self.keys()[idx];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// If you get a compile error on this line, it means that your generic eql
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// function is invalid for these parameters.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; eql = ctx.eql(key, test_key.*);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// verifyContext can&amp;#39;t verify the return type of generic eql functions,
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// so we need to double-check it here.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(eql) != &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@compileError&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Context &amp;#34;&lt;/span&gt; ++ &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeName&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(ctx)) ++ &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; has a generic eql function that returns the wrong type! bool was expected, but found &amp;#34;&lt;/span&gt; ++ &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeName&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(eql)));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (eql) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; idx;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        limit -= 1;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        idx = (idx + 1) &amp;amp; mask;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        metadata = self.metadata.? + idx;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Assuming that it is as fast, let&amp;rsquo;s look at another optimization: NaN Boxing.&lt;/p&gt;
&lt;p&gt;Now, this is something completely new to me - I&amp;rsquo;m not sure if I ever heard of it.
Anyway, now we need to re-implement the &lt;code&gt;Value&lt;/code&gt; struct:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; NanBoxedValue = &lt;span style=&#34;font-weight:bold&#34;&gt;packed&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    data: &lt;span style=&#34;font-weight:bold&#34;&gt;u64&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; SIGN_BIT: &lt;span style=&#34;font-weight:bold&#34;&gt;u64&lt;/span&gt; = 0x8000000000000000;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; QNAN: &lt;span style=&#34;font-weight:bold&#34;&gt;u64&lt;/span&gt; = 0x7ffc000000000000;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Nil = NanBoxedValue{ .data = QNAN | 1 };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; True = NanBoxedValue{ .data = QNAN | 3 };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; False = NanBoxedValue{ .data = QNAN | 2 };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We start with defining some constants.
Previously, &lt;code&gt;Nil&lt;/code&gt;, &lt;code&gt;True&lt;/code&gt;, and &lt;code&gt;False&lt;/code&gt; were top-level constants, but I&amp;rsquo;ve moved them into the struct, so then we could get the correct ones via a compile-time alias.
I did the same with the &lt;code&gt;UnionValue&lt;/code&gt; struct, previously named &lt;code&gt;Value&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, we need to reimplement the &lt;code&gt;is&lt;/code&gt;, &lt;code&gt;as&lt;/code&gt;, and &lt;code&gt;from&lt;/code&gt; methods.
I&amp;rsquo;m glad that I made them generic:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; NanBoxedValue = &lt;span style=&#34;font-weight:bold&#34;&gt;packed&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; is(self: NanBoxedValue, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; target: &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(.enum_literal)) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@hasField&lt;/span&gt;(ObjType, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@tagName&lt;/span&gt;(target))) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.is(.Obj)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; o = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(*Obj, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@ptrFromInt&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.data &amp;amp; ~(SIGN_BIT | QNAN)))));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; o.objType == target;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (target) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Bool =&amp;gt; (self.data &amp;amp; False.data) == False.data,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Nil =&amp;gt; self.data == Nil.data,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Number =&amp;gt; (self.data &amp;amp; QNAN) != QNAN,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Obj =&amp;gt; (self.data &amp;amp; (QNAN | SIGN_BIT)) == (QNAN | SIGN_BIT),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; as(self: NanBoxedValue, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; T: &lt;span style=&#34;font-weight:bold&#34;&gt;type&lt;/span&gt;) T {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@hasField&lt;/span&gt;(ObjType, typeNameUnqualified(T)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(*Obj, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@ptrFromInt&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.data &amp;amp; ~(SIGN_BIT | QNAN))))).as(&lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@typeInfo&lt;/span&gt;(T)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .Pointer =&amp;gt; |p| p.child,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; T,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (T) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@bitCast&lt;/span&gt;(self.data)),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; =&amp;gt; self.data == True.data,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; =&amp;gt; Nil.data,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            *Obj =&amp;gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(*Obj, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@ptrFromInt&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;usize&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intCast&lt;/span&gt;(self.data &amp;amp; ~(SIGN_BIT | QNAN))))),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;inline&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; from(x: anytype) NanBoxedValue {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@TypeOf&lt;/span&gt;(x)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;i32&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime_int&lt;/span&gt; =&amp;gt; NanBoxedValue{ .data = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;u64&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@bitCast&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@floatFromInt&lt;/span&gt;(x)))) },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;comptime_float&lt;/span&gt; =&amp;gt; NanBoxedValue{ .data = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;u64&lt;/span&gt;, &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@bitCast&lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@as&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;, x))) },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (x) True &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; False,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; =&amp;gt; Nil,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            *Obj =&amp;gt; NanBoxedValue{ .data = SIGN_BIT | QNAN | &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@intFromPtr&lt;/span&gt;(x) },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; =&amp;gt; &lt;span style=&#34;font-weight:bold&#34;&gt;unreachable&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Lastly, we need the remaining &lt;code&gt;isFalse&lt;/code&gt;, &lt;code&gt;format&lt;/code&gt;, &lt;code&gt;equal&lt;/code&gt;, and &lt;code&gt;mark&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; NanBoxedValue = &lt;span style=&#34;font-weight:bold&#34;&gt;packed&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;struct&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; isFalsey(self: NanBoxedValue) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.is(.Bool)) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; !self.as(&lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.is(.Nil)) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;false&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; equal(self: NanBoxedValue, other: NanBoxedValue) &lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.is(.Number) &lt;span style=&#34;font-weight:bold&#34;&gt;and&lt;/span&gt; other.is(.Number)) &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.as(&lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;) == other.as(&lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; self.data == other.data;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; mark(self: NanBoxedValue, vm: *VM) !&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.is(.Obj))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.as(*Obj).mark(vm);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; format(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        self: NanBoxedValue,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;comptime&lt;/span&gt; fmt: []&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;u8&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        options: std.fmt.FormatOptions,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        out_stream: anytype,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    ) !&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _ = fmt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        _ = options;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.is(.Number)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; out_stream.print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{d}&amp;#34;&lt;/span&gt;, .{self.as(&lt;span style=&#34;font-weight:bold&#34;&gt;f64&lt;/span&gt;)});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.is(.Bool)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; out_stream.print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;{}&amp;#34;&lt;/span&gt;, .{self.as(&lt;span style=&#34;font-weight:bold&#34;&gt;bool&lt;/span&gt;)});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (self.is(.Nil)) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; out_stream.print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;nil&amp;#34;&lt;/span&gt;, .{});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        } &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; self.as(*Obj).print(out_stream);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Notice that we&amp;rsquo;re no longer using a constant dispatch on the enum tag - instead, it&amp;rsquo;s a chain of &lt;code&gt;if&lt;/code&gt; &lt;code&gt;else&lt;/code&gt;.
Well, that is a small price to pay, as we rarely print things, compared to overall execution.&lt;/p&gt;
&lt;p&gt;After implementing this type of &lt;code&gt;Value&lt;/code&gt; struct, we can tell the rest of the implementation to use it like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; Value = &lt;span style=&#34;font-weight:bold&#34;&gt;if&lt;/span&gt; (NAN_BOXING) NanBoxedValue &lt;span style=&#34;font-weight:bold&#34;&gt;else&lt;/span&gt; UnionValue;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And the rest of the code, hopefully, works.
I had to make some small adjustments though.&lt;/p&gt;
&lt;p&gt;Now, running the benchmark shows takes &lt;code&gt;5.4649999141693115&lt;/code&gt; seconds.
A great improvement!&lt;/p&gt;
&lt;h2 id=&#34;thoughts-on-the-book&#34;&gt;Thoughts on the book&lt;/h2&gt;
&lt;p&gt;The book is great.
The writing style is engaging, I really liked the diagrams, and the material is properly structured.
Would recommend.
This is my second read, mind you.&lt;/p&gt;
&lt;p&gt;Perhaps, I was too harsh at times, but I just was frustrated with some things and let it out.&lt;/p&gt;
&lt;p&gt;Now, I do think that the lack of arrays, and plain hash tables is a bit of a bummer.
I get it - it is a learning exercise, but, it would be great to have just a bit more from actual languages.
Also, it would be really interesting to look at JIT and FFI, but I guess it deserves its own book already.&lt;/p&gt;
&lt;p&gt;All in all, I&amp;rsquo;m glad that I read this book.
It allowed me to tighten my Clojure skills in the past, and learn an awesome language today - Zig.&lt;/p&gt;
&lt;h2 id=&#34;thoughts-on-zig&#34;&gt;Thoughts on Zig&lt;/h2&gt;
&lt;p&gt;I really like Zig.&lt;/p&gt;
&lt;p&gt;At times I thought to myself - I am enjoying this way too much.
As you may know, I was a C programmer before, and I did some pretty low-level stuff in it.
I got tired of C and decided that I didn&amp;rsquo;t want to write in these kinds of languages.
Rust gave me hope, but it fell apart before my eyes.&lt;/p&gt;
&lt;p&gt;Zig, however, is a C I always wanted.
With a type system that actually helps reading and writing code, and not intended to do some convoluted nonsense.
I&amp;rsquo;ve written all of the code without an LSP, and it was a breeze.
The only tooling I used, besides the compiler, was Emacs tags.
Generating tags isn&amp;rsquo;t supported, and their precision is limited, but it was enough for this project.
If you&amp;rsquo;re interested, here&amp;rsquo;s how I generated the &lt;code&gt;TAGS&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;First, I made these regex rules for &lt;code&gt;etags&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/.*\&amp;lt;fn +\([a-zA-Z0-9_]+\) *(/\1/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/.*\&amp;lt;\(var\|const\) *\([a-zA-Z0-9_]+\) *= *\(extern\|packed\)? *\(struct\|enum\|union\)/\2/
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;/.*\&amp;lt;error +\([a-zA-Z0-9_]+\)/\1/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;src-block-caption&#34;&gt;
  &lt;span class=&#34;src-block-number&#34;&gt;Code Snippet 1:&lt;/span&gt;
  zig.etags
&lt;/div&gt;
&lt;p&gt;And added this to &lt;code&gt;Makefile&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-makefile&#34; data-lang=&#34;makefile&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ZIG_STD&lt;/span&gt; ?= ~/.zig/lib/std
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ZIG_STD_SOURCES&lt;/span&gt; := &lt;span style=&#34;font-weight:bold&#34;&gt;$(&lt;/span&gt;shell find &lt;span style=&#34;font-weight:bold&#34;&gt;$(&lt;/span&gt;ZIG_STD&lt;span style=&#34;font-weight:bold&#34;&gt;)&lt;/span&gt; -type f -name &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;*.zig&amp;#39;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ZIG_SOURCES&lt;/span&gt; := &lt;span style=&#34;font-weight:bold&#34;&gt;$(&lt;/span&gt;shell find ./src/zig -type f -name &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;*.zig&amp;#39;&lt;/span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tags&lt;/span&gt;:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	etags --language=none --regex=@zig.etags &lt;span style=&#34;font-weight:bold&#34;&gt;$(&lt;/span&gt;ZIG_SOURCES&lt;span style=&#34;font-weight:bold&#34;&gt;)&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;$(&lt;/span&gt;ZIG_STD_SOURCES&lt;span style=&#34;font-weight:bold&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It works well enough and allows jumping to the standard library.
I don&amp;rsquo;t use automatic completion that much even in other languages, and error checking is fine when I compile code.
Like old times.&lt;/p&gt;
&lt;p&gt;Sometimes the errors are weird:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zig build -Doptimize=Debug -p ./target/zig --cache-dir ./target/zig/.cache
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;zig build-exe lox-0.1.77 Debug native: error: the following command failed with 1 compilation errors:
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~/Downloads/zig-linux-x86_64-0.11.0/zig build-exe ~/Git/lox/src/zig/lox/main.zig --cache-dir ./target/zig/.cache --global-cache-dir ~/.cache/zig --name lox-0.1.77 --listen=-
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Build Summary: 0/3 steps succeeded; 1 failed (disable with --summary none)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;install transitive failure
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;+- install lox-0.1.77 transitive failure
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   +- zig build-exe lox-0.1.77 Debug native 1 errors
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;~/Downloads/zig-linux-x86_64-0.11.0/lib/std/fmt.zig:87:9: error: expected tuple or struct argument, found void
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Like, OK, where exactly is the error though?&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the source code that generates the message above.
Can you spot the problem?&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zig&#34; data-lang=&#34;zig&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; std = &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;@import&lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;std&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;pub&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;fn&lt;/span&gt; main() !&lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;const&lt;/span&gt; stdout = std.io.getStdOut().writer();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;try&lt;/span&gt; stdout.print(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Hello, world!&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\n&lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&lt;/span&gt;, {});
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yup, I forgot the &lt;code&gt;.&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;There are other such errors, I just didn&amp;rsquo;t bother to save more.&lt;/p&gt;
&lt;p&gt;Zig&amp;rsquo;s build system is something else.
Can&amp;rsquo;t say I like it, but I don&amp;rsquo;t dislike it either.
I guess I need to spend a bit more time with it to say for sure.
The inability to set the cache and target directories from &lt;code&gt;build.zig&lt;/code&gt; is a bummer though.&lt;/p&gt;
&lt;p&gt;Also, the language name is, well, weird.
The Crafting Interpreters book starts by explaining why the language is called Lox.
In the &lt;a href=&#34;http://craftinginterpreters.com/introduction.html#design-note&#34; target=&#34;_blank&#34;&gt;design note&lt;/a&gt; they mention Nim:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ol start=&#34;4&#34;&gt;
&lt;li&gt;It doesn’t have negative connotations across a number of cultures.
This is hard to be on guard for, but it’s worth considering.
The designer of Nimrod ended up renaming his language to “Nim” because too many people remember that Bugs Bunny used “Nimrod” as an insult.
(Bugs was using it ironically.)&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Well, the name &amp;ldquo;Zig&amp;rdquo;, in my country at least, &lt;em&gt;sounds&lt;/em&gt; a lot like the beginning of a &lt;a href=&#34;https://en.wikipedia.org/wiki/Nazi_salute&#34; target=&#34;_blank&#34;&gt;Nazi salute&lt;/a&gt;.
And when translated and spelled it has literally the same letters.
I&amp;rsquo;m sure it is not intentional, but I had a hard time talking about this language to basically anyone.
Literally, everyone was like: &amp;ldquo;name&amp;rsquo;s weird&amp;rdquo;.
So I started calling it ZigLang instead.&lt;/p&gt;
&lt;p&gt;Apart from that, I really enjoy this language, and maybe will use it for other projects in the future.&lt;/p&gt;
&lt;h2 id=&#34;closing-thought&#34;&gt;Closing thought&lt;/h2&gt;
&lt;p&gt;Thank you for reading through this insanely enormous flow of consciousness.
And if you did not read it fully, I appreciate that you still got to the end.
Even if you just scrolled past everything.&lt;/p&gt;
&lt;p&gt;This post was about two years in the making.
I&amp;rsquo;m really glad that I&amp;rsquo;ve finally finished it, and I hope it is interesting and informative.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in the project&amp;rsquo;s source code, you can find it here: &lt;a href=&#34;https://gitlab.com/andreyorst/lox&#34; target=&#34;_blank&#34;&gt;lox&lt;/a&gt;.
And if you&amp;rsquo;re a seasoned Zig developer, I would appreciate it if you reviewed the code.
I am by no means an expert in Zig, so I probably made a lot of stupid decisions.&lt;/p&gt;
&lt;p&gt;Let me know what you think!&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;because even this didn&amp;rsquo;t work later and I just symlinked the source directory into tests, because of course&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;Common Lisp is compiled to native code and loaded without requiring application restart.&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;Just call them the homework.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:4&#34;&gt;
&lt;p&gt;Technically, there&amp;rsquo;s more, but there are no sub-scopes like in other languages.&amp;#160;&lt;a href=&#34;#fnref:4&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Thoughts on Crafting Interpreters - Part 2&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Mon, 15 Jan 2024 07:02:00 +0300</pubDate>
    </item><item>
      <title>Thoughts on Crafting Interpreters - Part 1</title>
      <link>https://andreyor.st/posts/2023-12-03-thoughts-on-crafting-interpreters-part-1/</link>
      <guid>https://andreyor.st/posts/2023-12-03-thoughts-on-crafting-interpreters-part-1/</guid>
      <description>&lt;p&gt;Today I would like to discuss the &lt;a href=&#34;http://craftinginterpreters.com/&#34; target=&#34;_blank&#34;&gt;Crafting Interpreters&lt;/a&gt; book by Robert Nystrom.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a book about designing an interpreter for a dynamic programming language called Lox.
Well, not exactly.
It&amp;rsquo;s split into two parts - in the first is about crafting a tree-walking interpreter, and the second is about writing a complete bytecode VM.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m also going to write two posts, one for each part of the book.
This particular one is on the first part, which I have completed a long time ago.
A year and a half, actually.
So most of the things I&amp;rsquo;m going to talk about here are not &lt;em&gt;fresh&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;In the book, Robert chose Java as a language for the first half of the book.
The reasoning behind it is practical and well thought out, but I simply don&amp;rsquo;t like Java.
So instead, I chose Clojure as an implementation language, because I felt that it would be a good exercise, allowing me to sharpen my skills a bit more.&lt;/p&gt;
&lt;p&gt;TL;DR for this post could be:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Clojure is a nice language, and fits this kind of task well enough, as the tree-walking interpreter is largely a data-manipulation task.
Clojure&amp;rsquo;s protocols provide a great way of solving the expression problem with no boilerplate when compared to the Visitor pattern.
Immutability helps tremendously, eliminating bugs related to state management, with little, yet noticeable cost in performance, for this particular task, at least.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Plus a few complaints about the book.&lt;/p&gt;
&lt;p&gt;Now, if you&amp;rsquo;re interested in more, I welcome you to read the rest of the post.
But first, let&amp;rsquo;s get this straight - I&amp;rsquo;ll try to follow the book&amp;rsquo;s structure here, but no promises.
While the book is well-structured, it&amp;rsquo;s hard to reference specific parts of the code, as some pieces of the interpreter are changed frequently through the chapters.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m glad I&amp;rsquo;ve kept the repository around, as it contains all of the commit history, however, until the second part of the book I was loose on commit structure.
E.g. my commits for the first half look like&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;a6f69c8 * use protocols to solve expression problem
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;7412fb2 * WIP AST
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;4068faf * WIP parser
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;7990eb4 * support escapes in strings
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;d9b3f02 * move tokenizer to its own namespace
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3d8a602 * add column info
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;186095f * tokenizer
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;While for the second half of the book it is structured much better:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;88dd209 * chapter 19: Strings
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;6116263 * chapter 18: Types of Values
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;742364c * chapter 17: Compiling Expressions
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;f1ceb50 * Chapter 16: Scanning on Demand
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;da0149c * chapter 15: A Virtual Machine
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;f2d8a18 * chapter 14: Chunks of Bytecode
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, forgive me if I mix things up in this post - the second part will be better structured.
And, to be clear, this post isn&amp;rsquo;t really about the code, but about the book, although there&amp;rsquo;s plenty of code here.
I will highlight interesting differences in Clojure and Java approaches but I would not consider this the main topic of this post.&lt;/p&gt;
&lt;h2 id=&#34;scanning&#34;&gt;Scanning&lt;/h2&gt;
&lt;p&gt;For the first chapter, we start with scanning.
The chapter introduces various concepts, like error handling, but what I&amp;rsquo;d like to focus on here is token handling instead.&lt;/p&gt;
&lt;p&gt;In the book, Robert uses an enumeration type, which is probably how it is done in the Java world:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;com.craftinginterpreters.lox&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;enum&lt;/span&gt; TokenType {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Single-character tokens.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;  LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note, I don&amp;rsquo;t know Java - never learned it for real, and went straight to Clojure.
So if you&amp;rsquo;re curious if it&amp;rsquo;s OK to go into Clojure without knowing Java first - it is.
Although, I did have some Scheme background.&lt;/p&gt;
&lt;p&gt;So unlike the Java solution, I went with Clojure&amp;rsquo;s way of enumerating things.
Maps:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;single-token-type&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\(&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left_paren&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\)&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right_paren&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\{&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left_brace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\}&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right_brace&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\,&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:comma&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\.&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:dot&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\-&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:minus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:plus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:semicolon&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\*&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:star&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\=&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:equal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:less&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:greater&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\/&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:slash&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\!&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bang&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The same goes for all other token types.
It makes sense, as we&amp;rsquo;re essentially using the Enum as a lookup table for character dispatch.
Hence, instead of doing this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;char&lt;/span&gt; c = advance();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;switch&lt;/span&gt; (c) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;(&amp;#39;&lt;/span&gt;: addToken(LEFT_PAREN); &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;)&amp;#39;&lt;/span&gt;: addToken(RIGHT_PAREN); &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;{&amp;#39;&lt;/span&gt;: addToken(LEFT_BRACE); &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;}&amp;#39;&lt;/span&gt;: addToken(RIGHT_BRACE); &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;,&amp;#39;&lt;/span&gt;: addToken(COMMA); &lt;span style=&#34;font-weight:bold&#34;&gt;break&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We can do this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\(&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\)&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\{&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\}&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\,&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\.&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\-&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-token&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;single-token-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;error?&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\=&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\!&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\&amp;lt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\&amp;gt;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  )
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In other words, we share the body for all cases, and do a character lookup in the table to get the token type.
This eliminates just a little bit of duplication.&lt;/p&gt;
&lt;p&gt;Another thing to note, which is more important in my opinion, is that this parsing process is stateless.
In the Java version, the &lt;code&gt;addToken&lt;/code&gt; method modifies this class state.
While handy, I don&amp;rsquo;t like this approach, it makes things harder to test.
My version uses a conventional Clojure &lt;code&gt;loop&lt;/code&gt; and simply adds tokens to the collection, which is then returned from the loop:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokenize&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;source&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;at-end?&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;complement &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;partial &amp;gt; &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;source&lt;/span&gt;)))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt; 0     &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; current character&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt; 1        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; current line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; []     &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; tokens&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;error?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;false&lt;/span&gt;] &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; error indication&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;at-end?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; when finished return a tuple containing tokens and error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; indication&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;error?&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; otherwise, we take the `nth` character from the source, and&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; dispatch on it&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;nth &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;source&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;inc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;case&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\(&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\)&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\{&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\}&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\,&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\.&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\-&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\+&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;\*&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; Rebind the current char to the new `current` char;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; Use the same line, as none of these introduce a line change;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; Add new token to an immutable vector of `tokens`;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; pass `error?` as is, as no errors were introduced.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-token&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;single-token-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;c&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;error?&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ... rest of the clauses follow the same idea ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            ))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, tokenization is fully self-contained, and doesn&amp;rsquo;t require any state - it just accepts the string.
I later added the column counting to this code, but it&amp;rsquo;s beside the point now.&lt;/p&gt;
&lt;h2 id=&#34;representing-code&#34;&gt;Representing Code&lt;/h2&gt;
&lt;p&gt;This chapter mostly goes on how to read and define a BNF-like grammar.
However, what&amp;rsquo;s really interesting is the second part of this chapter - generating the tree representation generation code.
It is often referred to as metaprogramming, i.e. programs writing programs.&lt;/p&gt;
&lt;p&gt;At first, I was puzzled by this - do we really need to write Java to generate some classes for us based on grammar?
Well, I mean, there are libraries that can do that at runtime without an issue, like &lt;a href=&#34;https://github.com/engelberg/instaparse&#34; target=&#34;_blank&#34;&gt;instaparse&lt;/a&gt;, but in this case, we&amp;rsquo;re generating stuff even before compilation.
In other words, the book suggests generating source code.&lt;/p&gt;
&lt;p&gt;Well, that&amp;rsquo;s just macros, I thought to myself, and after studying a bit what the intention is, I made the following macro:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defmacro &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;define-ast&lt;/span&gt; [&amp;amp; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;specs&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;list* &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#39;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;for &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;spec&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;specs&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fields&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;str/split&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;spec&lt;/span&gt; #&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;\s+:\s+&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fields&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;str/split&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fields&lt;/span&gt; #&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;,?\s+&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;partition&lt;/span&gt; 2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;second&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;reduce &lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fields&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                       (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fields&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;symbol &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                     []))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             `(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defrecord &lt;/span&gt;~(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;symbol &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;) ~&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;fields&lt;/span&gt;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It expands the following grammar into a list of record definitions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljloc.ast&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;macroexpand-1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             &amp;#39;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;define-ast&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Binary   : Expr left, Token operator, Expr right&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Grouping : Expr expression&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Literal  : Object value&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Unary    : Token operator, Expr right&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clojure.core/defrecord&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Binary&lt;/span&gt; [&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;left &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clojure.core/defrecord&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Grouping&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expression&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clojure.core/defrecord&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Literal&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clojure.core/defrecord&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Unary&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;However I realized that it is a bit overkill to do it this way, so I ditched the macro completely.
After all, writing these records requires much less work in Clojure than it is in Java, but we&amp;rsquo;ll get to that in a bit.&lt;/p&gt;
&lt;p&gt;For comparison, here&amp;rsquo;s a definition from the book:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;If&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;extends&lt;/span&gt; Stmt {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    If(Expr condition, Stmt thenBranch, Stmt elseBranch) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.condition = condition;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.thenBranch = thenBranch;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.elseBranch = elseBranch;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    @Override
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;R&amp;gt; R &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;accept&lt;/span&gt;(Visitor&amp;lt;R&amp;gt; visitor) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; visitor.visitIfStmt(&lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;final&lt;/span&gt; Expr condition;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;final&lt;/span&gt; Stmt thenBranch;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;final&lt;/span&gt; Stmt elseBranch;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And here&amp;rsquo;s the Clojure version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defrecord &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;If&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;condition&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;then&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;else&lt;/span&gt;])
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So, why does the book&amp;rsquo;s code appear to be more involved?&lt;/p&gt;
&lt;h3 id=&#34;the-visitor-pattern&#34;&gt;The Visitor pattern&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a pretty specific problem, often appearing in projects, like this - the &lt;a href=&#34;https://en.wikipedia.org/wiki/Expression_problem&#34; target=&#34;_blank&#34;&gt;expression problem&lt;/a&gt;.
In the Java world, one of the solutions is the Visitor pattern, which the Book then &lt;a href=&#34;http://craftinginterpreters.com/representing-code.html#the-visitor-pattern&#34; target=&#34;_blank&#34;&gt;explains thoroughly&lt;/a&gt;.
I will not go into full details here, you&amp;rsquo;re free to read the book if you&amp;rsquo;re interested.&lt;/p&gt;
&lt;p&gt;The script, that generates classes for statements also generates methods required for the Visitor pattern to work.
We then can override these methods for each resulting type, and that&amp;rsquo;s basically it.
In the book, it is explained by defining a pretty printer for AST, printing parsed data as S-expressions.
Oh, sweet irony.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how it is done for the &lt;code&gt;Binary&lt;/code&gt; expression:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;package&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;com.craftinginterpreters.lox&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;AstPrinter&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;implements&lt;/span&gt; Expr.Visitor&amp;lt;String&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  String &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;print&lt;/span&gt;(Expr expr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; expr.accept(&lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;private&lt;/span&gt; String &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;parenthesize&lt;/span&gt;(String name, Expr... exprs) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    StringBuilder builder = &lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; StringBuilder();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    builder.append(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;(&amp;#34;&lt;/span&gt;).append(name);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;for&lt;/span&gt; (Expr expr : exprs) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      builder.append(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      builder.append(expr.accept(&lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    builder.append(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;)&amp;#34;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; builder.toString();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  @Override
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;public&lt;/span&gt; String &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;visitBinaryExpr&lt;/span&gt;(Expr.Binary expr) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; parenthesize(expr.operator.lexeme,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              expr.left, expr.right);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// ...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here&amp;rsquo;s how it is done in Clojure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;;; protocols.clj&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.protocols&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;clojure.string&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;str&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defprotocol &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IStringable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;;; ast.clj&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;ns &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.ast&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:require&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.protocols&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:refer&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IStringable&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt;]])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:import&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.tokenizer&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Token&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defrecord &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Binary&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;left&lt;/span&gt;, ^&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt;, &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IStringable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;left &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;]}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;(%s %s %s)&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;left&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And that&amp;rsquo;s it.
But it doesn&amp;rsquo;t end here, because Clojure was designed in such a way that the expression problem is not a problem.&lt;/p&gt;
&lt;p&gt;We can extend other types with our protocol, even after these types are defined.
For, instance, here I extend the &lt;code&gt;Object&lt;/code&gt; to handle numbers, and any other objects, as well as &lt;code&gt;nil&lt;/code&gt; which is a special case for protocols in Clojure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-protocol&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IStringable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;cond &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;double?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;str/replace&lt;/span&gt; #&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;\.0$&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;nil? &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;nil&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:else&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;] &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;nil&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And there you have it - we don&amp;rsquo;t need the Visitor pattern in Clojure, and we&amp;rsquo;re free to extend existing methods with new classes at any point.
The book demonstrates that the pattern works by defining overrides for all other data types, and the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;static&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;void&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;main&lt;/span&gt;(String[] args) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    Expr expression = &lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; Expr.Binary(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; Expr.Unary(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; Token(TokenType.MINUS, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, 1),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; Expr.Literal(123)),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; Token(TokenType.STAR, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt;, &lt;span style=&#34;font-weight:bold&#34;&gt;null&lt;/span&gt;, 1),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; Expr.Grouping(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; Expr.Literal(45.67)));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    System.out.println(&lt;span style=&#34;font-weight:bold&#34;&gt;new&lt;/span&gt; AstPrinter().print(expression));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Which prints &lt;code&gt;(* (- 123) (group 45.67))&lt;/code&gt;.
We can do the same in the REPL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.ast&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ast/-&amp;gt;Binary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ast/-&amp;gt;Unary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Token.&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:minus&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;-&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt; [0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Token.&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;123&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt; [0 0]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Token.&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:star&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;*&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt; [0 0])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;              (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ast/-&amp;gt;Grouping&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;               (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Token.&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;45.67&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt; [0 0]))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;(* (- 123) (do 45.67))&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It is different a bit, as I&amp;rsquo;m passing a line number and a column as a tuple &lt;code&gt;[0 0]&lt;/code&gt; but other than that it is the same.
If you&amp;rsquo;re wondering, &lt;code&gt;Token&lt;/code&gt; also implements the &lt;code&gt;IStringable&lt;/code&gt; protocol:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defrecord &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Token&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pos&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;toString&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lexeme&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IStringable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;lexeme&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We&amp;rsquo;ll see more of the protocols stuff in a bit, so let&amp;rsquo;s move on.&lt;/p&gt;
&lt;h2 id=&#34;parsing-expressions&#34;&gt;Parsing Expressions&lt;/h2&gt;
&lt;p&gt;The parser described in the book is based on the recursive descent algorithm.
I like it, it&amp;rsquo;s simple and effective and works reliably.&lt;/p&gt;
&lt;p&gt;However, it is again done in the Java style, mutating private things in the Parser class.
I don&amp;rsquo;t like it, it&amp;rsquo;s error-prone and hard to track what&amp;rsquo;s happening.&lt;/p&gt;
&lt;p&gt;Instead, I made it functional and pure:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;parse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Parse a sequence of `Token`s into a sequence of expressions.&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;exprs&lt;/span&gt; []
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; 0]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;&amp;lt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expression&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;conj &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;exprs&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expr&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;exprs&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ExceptionInfo&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]} (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ex-data&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;token&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;col&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;token&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;log/errorf&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;[%s:%s] %s at &amp;#39;%s&amp;#39;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;line&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;col&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ex-message&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;str &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;token&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each rule then simply returns the expression object, and the next &lt;code&gt;n&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;consume&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;message&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(#{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;type&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;inc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;throw&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ex-info&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;message&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:n&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;}))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;if-some&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;token&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;token&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;throw&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ex-info&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Unfinished expression&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                             &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;dec &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)}))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;equality&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;loop &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;comparison&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;and &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expr&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:eof&lt;/span&gt;) (#{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bang_equal&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:equal_equal&lt;/span&gt;} (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;current&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;inc &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;previous&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            [&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;right &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;comparison&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tokens&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; [(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;Binary&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;n&lt;/span&gt;])))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Yes, this involves passing n around, but if the function API is consistent, all is well.
All functions in the parser accept a vector of &lt;code&gt;tokens&lt;/code&gt; and the current &lt;code&gt;n&lt;/code&gt; for a position in the array.
No exceptions to that.
Why would you want anything else?&lt;/p&gt;
&lt;p&gt;And it&amp;rsquo;s so much easier to test too:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.parser&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;equality&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; 1.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 1]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:plus&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 3]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; 1.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 5]} &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; starting from here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:equal_equal&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;==&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 7]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; 2.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 10]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:eof&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;EOF&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 11]}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         2)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt; 1.0},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:operator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:equal_equal&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;==&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 7]},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt; 2.0}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 5]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.parser&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;equality&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; 1.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 1]} &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; starting from here&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:plus&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 3]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; 1.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 5]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:equal_equal&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;==&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 7]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;2&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; 2.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 10]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                          {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:eof&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;EOF&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 11]}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;[{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:left&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt; 1.0},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:operator&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:plus&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 3]},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt; 1.0}},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:operator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:equal_equal&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;==&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 7]},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:right&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt; 2.0}}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 5]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Try doing that with a class that mutates &lt;code&gt;current&lt;/code&gt; with every &lt;code&gt;advance&lt;/code&gt; call.&lt;/p&gt;
&lt;h3 id=&#34;polymorphic-dispatch&#34;&gt;Polymorphic dispatch&lt;/h3&gt;
&lt;p&gt;And I must note, that the resulting AST is printed as a sequence of plain maps, each element is actually a class:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.parser&amp;gt;&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;[{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; 1.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 1]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:plus&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;+&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 3]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:number&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; 1.0, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 5]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:eof&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;EOF&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:literal&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;, &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:pos&lt;/span&gt; [1 6]}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;parse&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;first&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;class&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;cljlox.ast.Binary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is important because in Clojure we have two kinds of polymorphic dispatch.
Earlier in this post I&amp;rsquo;ve mentioned protocols, which is a class-based dispatch.
The other one is multimethod-based dispatch, which is a runtime data polymorphism.&lt;/p&gt;
&lt;p&gt;Both allow for creating generic functions, just in a bit different flavor.
For instance, here&amp;rsquo;s how multimethods are often described:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defmulti &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interact&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;fn &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;] [(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;a&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;b&lt;/span&gt;)]))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Here we have a generic function &lt;code&gt;interact&lt;/code&gt; which expects two arguments, each containing a &lt;code&gt;:type&lt;/code&gt; key, like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ship&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:ship&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Buran&amp;#34;&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;def &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rock&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:asteroid&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:mass&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt; 420000 &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:unit&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:kg&lt;/span&gt;}})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now we can define methods for these two to interact:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defmethod &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interact&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:ship&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:ship&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;other&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;println &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;%s docks %s&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;other&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defmethod &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interact&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:ship&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:asteroid&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this&lt;/span&gt; {{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;unit&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:mass&lt;/span&gt;}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;println&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;%s destroys asteroid of mass %s %s&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;unit&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defmethod &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interact&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:asteroid&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:ship&lt;/span&gt;] [{{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;unit&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:mass&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;other&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;println&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;asteroid of mass %s %s pierces the %s&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;unit&lt;/span&gt;) (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;other&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defmethod &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interact&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:asteroid&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:asteroid&lt;/span&gt;] [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;other&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;println&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;asteroid of mass %s %s collides with asteroid of mass %s %s&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:mass&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;this&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:mass&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:unit&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;other&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:mass&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt;) (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt; &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;other&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:mass&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:unit&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This means that the &lt;code&gt;interact&lt;/code&gt; function receives two maps, takes a &lt;code&gt;:type&lt;/code&gt; key from each, and forms a tuple &lt;code&gt;[type-a type-b]&lt;/code&gt;.
Then it looks as if it has a definition for said tuple, in our case we&amp;rsquo;ve defined a permutation of methods for &lt;code&gt;:ship&lt;/code&gt; and &lt;code&gt;:asteroid&lt;/code&gt;.
So if we call &lt;code&gt;interact&lt;/code&gt; with our objects, we would see this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interact&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ship&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rock&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Buran&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;destroys&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;asteroid&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mass&lt;/span&gt; 420000 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;kg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interact&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rock&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ship&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;asteroid&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mass&lt;/span&gt; 420000 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;kg&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;pierces&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;the&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Buran&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;user&amp;gt;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;interact&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rock&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rock&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;asteroid&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mass&lt;/span&gt; 420000 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;kg&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;collides&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;with&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;asteroid&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;of&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;mass&lt;/span&gt; 420000 &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;kg&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It makes sense to use multimethods when dealing with data, and while our AST is data, I choose protocols, because we don&amp;rsquo;t really need to dispatch over a combination of values.
Protocols are also more efficient, as they rely on JVM internal mechanisms for polymorphic dispatch.
Additional reasoning was that at work we don&amp;rsquo;t really use Protocols, so I wanted to try them out in something involved.&lt;/p&gt;
&lt;p&gt;A small downside is that it is a bit harder to represent plain data as AST nodes, as I have to use conversion functions, like &lt;code&gt;-&amp;gt;Binary&lt;/code&gt; that takes a map, and converts it to a record.
But it&amp;rsquo;s better to use Protocols here, so I don&amp;rsquo;t mind some extra preparation steps.
Especially since it really only affects the tests, not the actual code.&lt;/p&gt;
&lt;h2 id=&#34;evaluating-expressions&#34;&gt;Evaluating Expressions&lt;/h2&gt;
&lt;p&gt;And we&amp;rsquo;re back to Protocols vs Visitors.&lt;/p&gt;
&lt;p&gt;The book, once again, uses the Visitor pattern to implement all necessary methods to evaluate our syntax tree as a program.
I won&amp;rsquo;t go and repeat the comparison, instead, here&amp;rsquo;s how I&amp;rsquo;ve done it in CljLox:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; cljlox.evaluator&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defprotocol &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;locals&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Literal&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Grouping&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expr&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:expression&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;locals&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;expr&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;locals&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Unary&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;locals&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;right &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;right &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;locals&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;case&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:minus&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;do &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;check-number-op!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;- &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:bang&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truth?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;runtime-error&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Unsupported unary operator&amp;#34;&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt;})))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The key point here is that Protocols are open, it&amp;rsquo;s possible to extend them from other parts of the system.
It&amp;rsquo;s doable in both ways too - you can extend an existing protocol with a new class, or you can give an existing class a new protocol.
In this project, I use both &lt;code&gt;extend-protocol&lt;/code&gt; and &lt;code&gt;extend-type&lt;/code&gt; to provide all necessary method implementations.&lt;/p&gt;
&lt;h2 id=&#34;statements-and-state&#34;&gt;Statements and State&lt;/h2&gt;
&lt;p&gt;Now we have to deal with the state.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*env&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;atom&lt;/span&gt; {}))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s it.&lt;/p&gt;
&lt;h2 id=&#34;control-flow&#34;&gt;Control Flow&lt;/h2&gt;
&lt;p&gt;Implementing control flow is an interesting…&lt;/p&gt;
&lt;p&gt;Just kidding, let&amp;rsquo;s talk about state.&lt;/p&gt;
&lt;h2 id=&#34;statements-and-state&#34;&gt;Statements and State&lt;/h2&gt;
&lt;p&gt;So, state.
Yes, I&amp;rsquo;m using an &lt;code&gt;atom&lt;/code&gt; here to hold the state of the interpreter.
Probably I could have used a &lt;code&gt;volatile&lt;/code&gt; instead, but I chose &lt;code&gt;atom&lt;/code&gt; for some reason.
There are no threads in CljLox, at least not yet, so &lt;code&gt;volatile&lt;/code&gt; would work just as fine.
Later I switched to &lt;code&gt;volatile&lt;/code&gt;, though.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve changed/created the &lt;code&gt;evaluate&lt;/code&gt; method for &lt;code&gt;Var&lt;/code&gt;, &lt;code&gt;Variable&lt;/code&gt; and &lt;code&gt;Assign&lt;/code&gt; nodes of the Ast:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Var&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt;]}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*env&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;assoc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;some?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Variable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;]}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;val &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;get &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*env&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;) &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;::not-found&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= val &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;::not-found&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;runtime-error&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Undefined variable &amp;#39;%s&amp;#39;.&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)) {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Assign&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;]}]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;val &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;contains? &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*env&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*env&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;runtime-error&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Undefined variable &amp;#39;%s&amp;#39;.&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)) {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;})))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This, however, only handles the global state, so I later had to change it to this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-env&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([] (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;parent&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;atom&lt;/span&gt; {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:enclosing&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;parent&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:values&lt;/span&gt; {}})))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defonce &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;*global-env&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-env&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#888;font-style:italic&#34;&gt;;; ...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-variable&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;font-weight:bold&#34;&gt;var &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;assoc-in&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:values&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt;] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Var&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;set-variable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;           (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;some?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;             (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;initializer&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defn &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-variable&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; @&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;values&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:values&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;contains? &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;values&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;get &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;values&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;if-some&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;enclosing&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:enclosing&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;recur&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;enclosing&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;runtime-error&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Undefined variable &amp;#39;%s&amp;#39;.&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;) {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt;})))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Variable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;get-variable&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Assign&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;name &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;val &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;value&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;contains? &lt;/span&gt;@&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;assoc &lt;/span&gt;(&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;) &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;runtime-error&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Undefined variable &amp;#39;%s&amp;#39;.&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)) {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;})))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Block&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;statements&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;&amp;#39; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;doseq &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;statement&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;statements&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;statement&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;&amp;#39;)))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s a lot of code to read, so I&amp;rsquo;ll outline the changes.&lt;/p&gt;
&lt;p&gt;First, now the &lt;code&gt;evaluate&lt;/code&gt; method accepts two arguments, instead of just one.
Yes, we&amp;rsquo;re now passing the environment around.
In a non-functional interpreter, we could just set the current environment of the &lt;code&gt;Evaluator&lt;/code&gt; class, once we introduce new or leave a scope but here we can&amp;rsquo;t do that.
Err, we &lt;em&gt;can&lt;/em&gt;, I just chose not to, because again - it is much easier to reason about the code.
The environment is just a map wrapped into an atom, after all.&lt;/p&gt;
&lt;h2 id=&#34;control-flow&#34;&gt;Control Flow&lt;/h2&gt;
&lt;p&gt;Aside from adding a few new extensions to the protocol:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;If&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;condition&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;then&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;else&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;test &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;condition&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truth?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;test&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;then&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;else&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Logical&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;left &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;right&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;left &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;left &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;case&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;operator&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:or&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truth?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;left&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;left&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;right &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:and&lt;/span&gt; (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;not &lt;/span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;truth?&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;left&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;left&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;right &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;we also implement loops in this section.
While I like the approach of implementing &lt;code&gt;while&lt;/code&gt; in the host language, and &lt;code&gt;for&lt;/code&gt; terms of our definition of &lt;code&gt;while&lt;/code&gt;, honestly, I would prefer a tour about tail call elimination instead.
It would probably make things more complicated, but I feel that it would bring more value to the table.
Since this book teaches how to create a language, I think it is worth mentioning the tail call recursion approach at the very least.&lt;/p&gt;
&lt;p&gt;When I was programming in C and had no idea an infinite recursion was even possible, learning that there are some languages that can do that was a huge revelation.
How many algorithms could I have written in far less complicated ways, by using the continuation passing style?
Yeah, a weird statement to make, but CSP can be easier to understand at times.&lt;/p&gt;
&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;
&lt;p&gt;Now we&amp;rsquo;re getting into the meat of the interpreter.
We can put together all our variables, scopes, and loops, and wrap them into something we can define and call later.
Everything starts with a different protocol:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defprotocol &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ICallable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;call&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arguments&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And later we can extend it with new types:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;LoxCallable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ICallable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;call&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arity&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;function&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arguments&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arity&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arguments&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;apply &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arguments&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;runtime-error&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Expected %s arguments but got %s.&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arity&lt;/span&gt; (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;count &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arguments&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       {&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:token&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;token&lt;/span&gt;}))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-protocol&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ICallable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Object&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;call&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &amp;amp; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rest&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;runtime-error&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Can only call functions and classes.&amp;#34;&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;nil&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;call&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &amp;amp; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;rest&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;runtime-error&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;Can only call functions and classes.&amp;#34;&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Again, I really like this feature of Clojure - defining a new protocol and extending it with already existing types like &lt;code&gt;Object&lt;/code&gt; or &lt;code&gt;nil&lt;/code&gt;, is great.
Same thing with already existing types, such as &lt;code&gt;LoxCallable&lt;/code&gt; (used for native interpreter&amp;rsquo;s functions) - we can just give it a new protocol and implement it.
No need for visitors, you just do:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;extend-type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IInterpretable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; [{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;] &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:as&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;LoxFunction.&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;when &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;assoc-in&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:values&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;name&lt;/span&gt;)] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;f&lt;/span&gt;)))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And then:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-clojure&#34; data-lang=&#34;clojure&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;defrecord &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;LoxFunction&lt;/span&gt; [^&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;Function&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;declaration&lt;/span&gt;, &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;closure&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ICallable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;call&lt;/span&gt; [{{&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:keys&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;params&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;body&lt;/span&gt;]} &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:declaration&lt;/span&gt;} &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;_&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;make-env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;closure&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;doseq &lt;/span&gt;[[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arg&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;] (&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;map vector &lt;/span&gt;&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;params&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;args&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;swap!&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;assoc-in&lt;/span&gt; [&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:values&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;arg&lt;/span&gt;))] &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;val&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;evaluate&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;body&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;env&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;catch&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ExceptionInfo&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (&lt;span style=&#34;font-weight:bold&#34;&gt;let &lt;/span&gt;[&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;data&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;ex-data&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e&lt;/span&gt;)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (&lt;span style=&#34;font-weight:bold&#34;&gt;if &lt;/span&gt;(&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;= &lt;/span&gt;&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:return&lt;/span&gt; (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:type&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;data&lt;/span&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:value&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;data&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;e&lt;/span&gt;))))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;IStringable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;tostring&lt;/span&gt; [&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;format&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;&amp;#34;#&amp;lt;function: %s&amp;gt;&amp;#34;&lt;/span&gt; (&lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;-&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style=&#34;color:#666;font-weight:bold;font-style:italic&#34;&gt;self&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:declaration&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:name&lt;/span&gt; &lt;span style=&#34;color:#666;font-style:italic&#34;&gt;:lexeme&lt;/span&gt;))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every time I read things like &lt;code&gt;visitFunctionStmt&lt;/code&gt; I question myself - what exactly visiting does do, why does it create an object, and so on?
Well, I&amp;rsquo;m not a Java programmer for a reason, I guess, visitors, abstract fabrics, and other such things don&amp;rsquo;t tickle my fancy.&lt;/p&gt;
&lt;h2 id=&#34;resolving-and-binding&#34;&gt;Resolving and Binding&lt;/h2&gt;
&lt;p&gt;I know, I&amp;rsquo;m being a bit shallow on details, but honestly, I just don&amp;rsquo;t remember well what was going on in my mind back then.
The resolver, however, is another thing that I took the liberty to make immutable, so it&amp;rsquo;s quite different from the book.
I have a &lt;a href=&#34;https://gitlab.com/andreyorst/cljlox/-/commit/e25dbca7d814bdbc71e93f9869a21992687ca7ee&#34; target=&#34;_blank&#34;&gt;giant commit&lt;/a&gt; where I basically change this in every protocol method:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; (defprotocol ICallable
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-  (call [self arguments token env]))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+  (call [self arguments token env locals]))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Well, why would I do that?
No reason, really.
I just noticed that the only place I change locals is in the evaluation entry point and each new scope.
However, none of these have to use the mutable state, as it is purely for convenience (and the style the book is written in), so I changed it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(defn run
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([source]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (run source nil))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  ([source file]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (let [fmt (if file (str file &#34; %s&#34;) &#34;%s&#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;         {:keys [errors tokens]} (tokenize source)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (if (seq errors)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        (with-out-err
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (doseq [error errors]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            (println (format fmt (str error)))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-       (let [expressions (parse tokens)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-         (reset! *locals {})
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-         (doseq [expr expressions]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-           (lox-resolve expr []))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+       (let [expressions (parse tokens)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+             locals (reduce (fn [locals expr]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+                              (merge locals (second (lox-resolve expr [[] {}]))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+                            {} expressions)]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;          (reduce (fn [_ expr]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    (when (seq expr)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-                     (interpret expr)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+                     (interpret expr locals)))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                  nil expressions))))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A similar change was needed in the &lt;code&gt;resolve-local&lt;/code&gt; function, as now it would use an additional storage passed in as an argument:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-diff&#34; data-lang=&#34;diff&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-(defn- resolve-local [expr name scope-stack]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+(defn- resolve-local [expr name [scope-stack locals]]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   (when (seq scope-stack)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     (loop [i (dec (count scope-stack))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       (if (contains? (get scope-stack i) (:lexeme name))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-        (register-expr-scope expr (- (count scope-stack) 1 i))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-        (when (&amp;gt; i 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-removed&#34;&gt;-          (recur (dec i)))))))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+        [scope-stack (assoc locals expr (- (count scope-stack) 1 i))]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+        (if (&amp;gt; i 0)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+          (recur (dec i))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span class=&#34;diff-added&#34;&gt;+          [scope-stack locals])))))
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;With the rest of the changes the resolver is fully immutable, but is it worth the effort?
Well, kinda - it is much easier to debug, and I was able to walk the code, looking at when the locals appeared in the storage much easier.
I could, theoretically, make the same change for the global scope storage, but that would be way too much work, and I was tired of this change already.
That would help to deal with the annoyance that the scope storage refers to itself at some point, making the debugger unhappy and cycling infinitely during result inspection.&lt;/p&gt;
&lt;p&gt;And yes, &lt;a href=&#34;https://gitlab.com/andreyorst/cljlox/-/commit/92430e8048ad1c1f4151f6e22c61be666815addf&#34; target=&#34;_blank&#34;&gt;later&lt;/a&gt; I had to store locals in the &lt;code&gt;volatile!&lt;/code&gt; storage to keep them in the REPL, but not because it is mandatory, I was just lazy to put it into the loop.&lt;/p&gt;
&lt;h2 id=&#34;classes&#34;&gt;Classes&lt;/h2&gt;
&lt;p&gt;We&amp;rsquo;re entering the part of the book I don&amp;rsquo;t like, yay!
As you know, I like Clojure, but not really because it is a Lisp.
I like Clojure because it is a functional language without a type system burden.&lt;/p&gt;
&lt;p&gt;If I were into functional programming &lt;strong&gt;and&lt;/strong&gt; into type systems, I would be probably writing about Haskell or Idris, but I&amp;rsquo;m writing about Clojure, and more often Lua/Fennel.
If I were into Lisp &lt;strong&gt;and&lt;/strong&gt; LISP, I would probably be writing about Common Lisp &lt;em&gt;or&lt;/em&gt; Scheme.
But I&amp;rsquo;m into type-less, functional approach so Clojure is a perfect fit for me.
Well, maybe Elixir as well, but they&amp;rsquo;re bringing a type system in, so I guess they&amp;rsquo;re off track on what makes the language fun.
But I digress.&lt;/p&gt;
&lt;p&gt;Out of all the features I dislike the most are classes and inheritance, and these are the final chapters of the first half of the book.
I dislike classes and inheritance mainly because they are only complicated things in my past experience.
I worked on a somewhat large code base in C++ before, and inheritance was a huge pain there.&lt;/p&gt;
&lt;p&gt;Other languages that feature classes often over-complicate things as well - look at Java with its visitors, factories, and such.
So I tend to dislike classes.
To be fair, there are use cases for this paradigm, and there are fine implementations like CLOS or Smalltalk, but I would not try to base everything on classes.&lt;/p&gt;
&lt;p&gt;Speaking of this book - why are we already at classes when we didn&amp;rsquo;t cover any base data structures?
There are strings, yes, but where are arrays and records/hash-maps?
What about tuples?
Some could argue that strings &lt;em&gt;can&lt;/em&gt; be used for arrays or their code could be repurposed, but not in our case, as we&amp;rsquo;re using the host platform&amp;rsquo;s strings which are immutable.
Implementing strings as byte arrays is a thing, but it&amp;rsquo;s not what the book did, so there are simply no arrays in Lox.&lt;/p&gt;
&lt;p&gt;Well, we can implement a linked list with classes, but there&amp;rsquo;s literally no way to implement an array without explicit access to the memory.
I don&amp;rsquo;t really want to cover the changes in the code base, as there&amp;rsquo;s nothing you haven&amp;rsquo;t seen before in this post.&lt;/p&gt;
&lt;p&gt;One thing I do want to cover though is the use of classes to implement namespaces.
This is covered in the &amp;ldquo;Challenges&amp;rdquo; section after the actual chapter:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;We have methods on instances, but there is no way to define “static” methods that can be called directly on the class object itself. Add support for them. Use a class keyword preceding the method to indicate a static method that hangs off the class object.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Math&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;font-weight:bold&#34;&gt;class&lt;/span&gt; square(n) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; n * n;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print &lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;Math&lt;/span&gt;.square(3); &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Prints &amp;#34;9&amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You can solve this however you like, but the “metaclasses” used by Smalltalk and Ruby are a particularly elegant approach. Hint: Make LoxClass extend LoxInstance and go from there.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Saying I dislike this approach is to not say anything.
Why would you do that?
It&amp;rsquo;s like stating: &amp;ldquo;Our language can&amp;rsquo;t do namespaces but do not worry, we have static methods that provide exactly the same thing, you just do it the ugly way&amp;rdquo;.
Well, it probably makes sense in some languages like Smalltalk, but not everything is Smalltalk.&lt;/p&gt;
&lt;p&gt;Take a look at Lua for a second.
It doesn&amp;rsquo;t have namespaces.
It doesn&amp;rsquo;t have classes either.
Yet, it does have a way of defining modules - it just uses hash tables for that.
And it does the same thing with classes - you use a hash table for that.
You don&amp;rsquo;t have to be Clojure to just use maps!&lt;/p&gt;
&lt;p&gt;Then the book proceeds:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Most modern languages support “getters” and “setters”—members on a class that look like field reads and writes but that actually execute user-defined code. Extend Lox to support getter methods. These are declared without a parameter list. The body of the getter is executed when a property with that name is accessed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Every time I see this, I ask myself &amp;ldquo;Why?!&amp;rdquo; - a pointless question.&lt;/p&gt;
&lt;p&gt;Look at this code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;class&lt;/span&gt; Circle {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  init(radius) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.radius = radius;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  area {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;return&lt;/span&gt; 3.141592653 * &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.radius * &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.radius;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; circle = Circle(4);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print circle.area; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// Prints roughly &amp;#34;50.2655&amp;#34;.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Accessing the &lt;code&gt;area&lt;/code&gt; &lt;em&gt;field&lt;/em&gt; we get the area of a circle with the radius of &lt;code&gt;4&lt;/code&gt; units.
Cool, right?&lt;/p&gt;
&lt;p&gt;Now look at this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;background-color:#fff;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;class&lt;/span&gt; Circle {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  init(radius) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;this&lt;/span&gt;.radius = radius;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  area {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;font-weight:bold&#34;&gt;while&lt;/span&gt;(&lt;span style=&#34;font-weight:bold&#34;&gt;true&lt;/span&gt;) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold;font-style:italic&#34;&gt;var&lt;/span&gt; circle = Circle(4);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;print circle.area; &lt;span style=&#34;color:#888;font-style:italic&#34;&gt;// good luck debugging this
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Surely, looking at the &lt;code&gt;circle.area&lt;/code&gt; part of the code you can&amp;rsquo;t see that there&amp;rsquo;s a call there.
That&amp;rsquo;s why we have syntax, mind you!
This &amp;ldquo;feature&amp;rdquo; to me looks like a deliberate shot to the foot - the expression power it gives you is equal to not hitting two keys on the keyboard yet you introduce ambiguity to your language.&lt;/p&gt;
&lt;p&gt;It was at this point where I stopped even trying to do any of the so-called &amp;ldquo;Challenges&amp;rdquo;, but I will have to talk about them later, as I do have more things to say.&lt;/p&gt;
&lt;h2 id=&#34;inheritance&#34;&gt;Inheritance&lt;/h2&gt;
&lt;p&gt;Most of the changes in this section are sorely related to how we access methods, fields, and so on, so again, I won&amp;rsquo;t go into actual code differences.
Call me lazy.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m glad that the book went for a single inheritance approach though, as nothing gives me a stronger desire to punch someone than seeing a class that inherits from another 16, each of which also inherits from more than three.
I have seen this in the C++ codebase I mentioned before.
Looking up where the method is defined is hard enough, and this was a C++ written before things like language servers were a thing, so tags were the only way to navigate it in a somewhat intelligent way.
Unfortunately, generating tags was slow, and I had to update them frequently, as I made the changes to the code.
Often, the jump wasn&amp;rsquo;t possible because tags were outdated.&lt;/p&gt;
&lt;p&gt;So, having a single inheritance is, perhaps, limiting as you can&amp;rsquo;t go nuts and say that &lt;code&gt;Cat&lt;/code&gt; inherits from both &lt;code&gt;Animal&lt;/code&gt; and &lt;code&gt;Carnivore&lt;/code&gt;, which may be a bummer, I guess, but this is a textbook example, I have yet to see OOP code like that.
Personally, I&amp;rsquo;ll take single inheritance over multiple inheritance any time.
But I&amp;rsquo;d rather do no inheritance at all, to be honest, protocols are much more fun to use.&lt;/p&gt;
&lt;h2 id=&#34;final-thoughts&#34;&gt;Final thoughts&lt;/h2&gt;
&lt;p&gt;This post is a total trainwreck.
I should have published it in the middle of April 2022 but for some reason, I didn&amp;rsquo;t.
To be fair, I still have a draft of the first version of this post, and it is horrible, so I guess it&amp;rsquo;s good that I didn&amp;rsquo;t publish it before.
Such posts should be written during the time you spend with the book, not afterward, and especially not after almost two years.&lt;/p&gt;
&lt;p&gt;So that&amp;rsquo;s why I&amp;rsquo;ll be re-writing the second half of the book in &lt;a href=&#34;https://ziglang.org/&#34; target=&#34;_blank&#34;&gt;Zig&lt;/a&gt; and capturing my thoughts as I go through it!
For the &lt;strong&gt;second time&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Yes, I already tried this approach, but given that I didn&amp;rsquo;t know Zig at all back then the resulting code is terrible.
Can&amp;rsquo;t say I&amp;rsquo;m proud about the Clojure version either, but the Zig version is heaps and bounds worse in all areas.
Hopefully, this time around I will be able to do a better job.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve mentioned that I have more things to say about the &amp;ldquo;Challenges&amp;rdquo;, waiting for the reader at each chapter&amp;rsquo;s end.
I guess, this will have to wait for the second post, which I&amp;rsquo;m sure won&amp;rsquo;t take years to appear.
Ahem.&lt;/p&gt;
&lt;p&gt;You see, most of the challenges, or should I say, exercises were not really out of the way in the first half of the book.
Can&amp;rsquo;t say so for the second half though - I had major issues going through the book because I completed the challenges.
This wasn&amp;rsquo;t an issue for the first book because most challenges are easy, but this can&amp;rsquo;t be said for the second half, as we&amp;rsquo;re no longer in the managed territory.
Implementing your bytecode interpreter is much harder than using your host language for the heavy lifting.&lt;/p&gt;
&lt;p&gt;Anyway, I hope you found this post interesting enough to read til here.
If not, well, that&amp;rsquo;s fair, I didn&amp;rsquo;t find it interesting to read too, honestly.
But I had to get it out of my system, and hopefully, the second part will be more refined.&lt;/p&gt;
&lt;div class=&#34;comment-link&#34;&gt; &lt;a href=&#34;mailto:%61%6e%64%72%65%79%6f%72%73%74%2b%62%6c%6f%67%40%67%6d%61%69%6c%2e%63%6f%6d?subject=Comment: Thoughts on Crafting Interpreters - Part 1&#34; target=&#34;_blank&#34; rel=&#34;noopener noreferrer&#34;&gt;Comment via email&lt;/a&gt;&lt;/div&gt;</description>
      <pubDate>Sun, 03 Dec 2023 21:35:00 +0300</pubDate>
    </item>
  </channel>
</rss>
