<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>pthorpe92.dev</title>
      <link>https://pthorpe92.dev</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://pthorpe92.dev/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Sun, 22 Mar 2026 00:00:00 +0000</lastBuildDate>
      <item>
          <title>The absolute beginners guide to databasemaxxing</title>
          <pubDate>Sun, 22 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/databasemaxxing/</link>
          <guid>https://pthorpe92.dev/databasemaxxing/</guid>
          <description xml:base="https://pthorpe92.dev/databasemaxxing/">&lt;h2 id=&quot;so-you-are-interested-in-getting-started-learning-databases&quot;&gt;So, you are interested in getting started learning databases?&lt;&#x2F;h2&gt;
&lt;p&gt;I get a lot of emails from people asking me how they can begin to learn the vast world of databases, and whether they are far enough along on their programming journey to bother trying to start to learn this sub-genre of CS. This post is meant to be my authoritative answer to those questions... Sort of a database specific version of: &lt;a href=&quot;&#x2F;learn-systems&#x2F;&quot;&gt;this&lt;&#x2F;a&gt; post about programming in general.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;First&lt;&#x2F;em&gt;, lets answer the question of: &lt;code&gt;Is it the right time to start learning database internals?...&lt;&#x2F;code&gt; or &lt;code&gt;am I far enough along to begin?&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I would say that if you want to start learning DBMS internals, you should have completed at least a couple non-trivial projects, and you should be familiar with low level OS concepts, interacting with libc&#x2F;POSIX API&#x27;s. I &lt;em&gt;highly&lt;&#x2F;em&gt; recommend finishing an interpreter or compiler project before moving on to databases, because a compiler and a database are much more similar than you might imagine at first... Both are taking some code, parsing it into an AST and transforming it into  some output (in fact SQLite uses a bytecode VM internally, very similar to what you would see in an interpreter).&lt;&#x2F;p&gt;
&lt;p&gt;You should also be deeply familiar with &lt;strong&gt;using&lt;&#x2F;strong&gt; databases and writing SQL&#x2F;understanding JOIN&#x27;s and schemas and the relational model first... Don&#x27;t try to skip this step, as it will make everything that much more difficult later on. Some of this information may already be obvious to you, if you are an advanced &lt;em&gt;user&lt;&#x2F;em&gt; of databases, but will be explained anyway for brevity.&lt;&#x2F;p&gt;
&lt;p&gt;The rest of this post will assume you are roughly this far along, so I will not be defining things like &lt;code&gt;AST&lt;&#x2F;code&gt; because I will assume you are familiar with this at this point.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What if I am already familiar with DBMS internals?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Then this post is not for you: it is over-simplified in a way that attempts to make everything as easy to understand as possible for absolute beginners.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;common-terminology&quot;&gt;Common terminology&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s go over some terms that you might not have heard if you have only ever been on the &lt;em&gt;user&lt;&#x2F;em&gt; end of database systems: Not just their definition, but we&#x27;ll talk about in plain english what people mean when they use these terms. You will hear pretty much all these terms used frequently in the database world.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Remember&lt;&#x2F;strong&gt; these are somewhat simplified explanations, for their complete definitions, please refer to CMU Database Group&#x27;s courses and read the &lt;em&gt;Database Internals&lt;&#x2F;em&gt; book by Alex Petrov.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Databasemaxxing&lt;&#x2F;code&gt;: This is the brain-rot way of saying: &quot;living a Database-centric lifestyle&quot;. To dedicate one&#x27;s entire life to the study and practice of engineering database systems, choosing to live by the relational model.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;OLTP&lt;&#x2F;code&gt; or &lt;code&gt;OLTP system&lt;&#x2F;code&gt;: Simply means a &lt;em&gt;transactional&lt;&#x2F;em&gt; database system like Postgres, MySQL or SQLite. These systems are generally focused on short, transactional workloads with frequent writes and reads as quickly as possible while providing all the ACID guarantees we expect from database systems. These systems store values on disk in groups of Rows, much like you would imagine they would if you have ever used one.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;OLAP&lt;&#x2F;code&gt; or &lt;code&gt;OLAP system&lt;&#x2F;code&gt;: Conversely, this is an &lt;em&gt;analytical&lt;&#x2F;em&gt; database system like DuckDB, Snowflake or Clickhouse. These systems are focused on performing highly complex queries (think huge multi JOIN graphs with lots of aggregations), and write performance is generally far less of a concern than with OLTP systems: the performance focus is instead shifted to the query planner&#x2F;optimizer, to better handle extremely large, complex joins over many large tables where the data cannot fit in memory (or might not even be on the same computer&#x2F;node&#x2F;data-center). These database systems typically (but not always) store the underlying values by groups of Column instead of by Row... This is (partially) because it makes it easier to compress the data on disk, which is not something typically done by OLTP database systems.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;DDL&lt;&#x2F;code&gt;: Data Definition Language &#x2F; any SQL statements that define the schema, so: &lt;code&gt;CREATE TABLE&lt;&#x2F;code&gt;, &lt;code&gt;CREATE INDEX&lt;&#x2F;code&gt;, &lt;code&gt;DROP TABLE&lt;&#x2F;code&gt; etc.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;DML&lt;&#x2F;code&gt;: Data Manipulation Language, so think &lt;code&gt;INSERT&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;UPDATE&lt;&#x2F;code&gt; &#x2F; &lt;code&gt;DELETE&lt;&#x2F;code&gt; statements... Anything manipulating existing data in your database system.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;DQL&lt;&#x2F;code&gt;: Data Query Language: Obviously this would be your &lt;code&gt;SELECT&lt;&#x2F;code&gt; queries.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Tuple&lt;&#x2F;code&gt;: is just database-speak for a &lt;code&gt;row&lt;&#x2F;code&gt;.. I imagine it&#x27;s called this because a Row is very similar to the tuple you might know from your favorite programming language: one or more grouped values of various types.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Scan&lt;&#x2F;code&gt; or &lt;code&gt;Full scan&lt;&#x2F;code&gt;: The process of, or the reading of every single row in a table: So think, &quot;the query does a full scan of &#x27;t&#x27;&quot;, means that if &#x27;t&#x27; has N rows, the query had to read &lt;em&gt;all N rows&lt;&#x2F;em&gt; in order to return the result (and that result could be anywhere from 0..=N rows).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Row ID&lt;&#x2F;code&gt;: An internal identifier for a row&#x2F;tuple. Many storage engines use an integer row identifier (or something equivalent) which indexes store so the database can locate the row quickly. Some systems will use a declared INTEGER PRIMARY KEY as this ID: this is what&#x27;s referred to as a &quot;row id alias&quot;, because it is both a user facing column value, and also an internal identifier.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;ETL&lt;&#x2F;code&gt;: This stands for: &lt;em&gt;Extract, Transform, Load&lt;&#x2F;em&gt; and typically this means a job which pulls data (usually out of an OLTP system), it might do things like create new indexes that weren&#x27;t needed in the OLTP system but will be necessary or helpful to run analytical queries, and&#x2F;or otherwise makes the raw data more &#x27;structured&#x27;... Then loads it into an OLAP system to have analytical queries ran against it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Access method&lt;&#x2F;code&gt;: The way in which we are going to retrieve values from a given table... For example: if we have &lt;code&gt;WHERE indexed_column = 123&lt;&#x2F;code&gt;, then our access method would be an index seek on &lt;code&gt;indexed_column&lt;&#x2F;code&gt;... but if our query is &lt;code&gt;SELECT * from t;&lt;&#x2F;code&gt;: our access method would be a table scan, because our query requires us to fetch all the rows.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Seek&lt;&#x2F;code&gt; or &lt;code&gt;Index seek&lt;&#x2F;code&gt;: A fast lookup using an Index, which allows the database system to traverse quickly to the value or tuple in question. (You can think of this as essentially the opposite of a Scan... at least &lt;em&gt;generally&lt;&#x2F;em&gt;: Scan = bad&#x2F;slow, Seek = good&#x2F;fast)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Binding&lt;&#x2F;code&gt;: The process of making AST nodes aware of your schema: So lets say we have &lt;code&gt;SELECT a, b FROM t;&lt;&#x2F;code&gt;... This initially parses into something like:&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;    Stmt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Select&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;cols&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Ident&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Ident&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)]}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After the binding process, we would end up with something like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;   Stmt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Select&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   cols&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Column&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;ColumnRef&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;table&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; TableRef&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;t&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;},&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;a&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;},&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt;         Expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Column&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;ColumnRef&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;table&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; TableRef&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;t&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;},&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;b&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;} ) ))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and we have additional schema information encoded in the AST now, we know that &quot;t&quot; is a real table and it has columns &quot;a&quot; and &quot;b&quot; with internal ID&#x27;s of 0 and 1 (internal ID&#x27;s may just be the index of the col in the table)... It&#x27;s now more than just an &lt;code&gt;Identifier&lt;&#x2F;code&gt; and it&#x27;s aware of our actual schema. More info on this later.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;WAL&lt;&#x2F;code&gt;: Write-Ahead-Log: for several reasons, database systems usually do not write data directly to the main database file(s) during a transaction... Instead, writes are done to a separate, append-only file that contains the new&#x2F;changed data and metadata about the operation (or in the case of SQLite: the new version of each of the 4kb pages touched). WAL&#x27;s exist for several reasons:&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;ol&gt;
&lt;li&gt;Doing all your writes as append-only keeps data written sequentially, which is much faster than doing scattered writes across 1 or more files on each write transaction.&lt;&#x2F;li&gt;
&lt;li&gt;You now have a log of all transactions&#x2F;changes, which can be replayed in the event of a crash.. If you write directly to the DB file(s), you will have no idea on startup after your crashed, whether or not your active writes ever finished or were somehow corrupted. Since the WAL is only ever truncated &lt;strong&gt;after&lt;&#x2F;strong&gt; the contents are copied to the database file(s), we know that it&#x27;s contents have 100% safely been transferred over.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Snapshot isolation&lt;&#x2F;code&gt;: When transaction &lt;code&gt;t1&lt;&#x2F;code&gt; begins their transaction at time &lt;code&gt;t&lt;&#x2F;code&gt;, either implicitly or explicitly, they should only ever see the state of the database as it exists at time &lt;code&gt;t&lt;&#x2F;code&gt;: Meaning if they are scanning a table which gets inserted into by some transaction &lt;code&gt;t2&lt;&#x2F;code&gt; during the scan, it will not see &lt;code&gt;t2&lt;&#x2F;code&gt;&#x27;s rows. You can think of it like freezing the database right at the start of your transaction, each transaction should only ever see that frozen snapshot while that transaction is going on. (Not all databases use snapshot isolation by default, but many modern ones do. There are other levels of transaction isolation, such as &quot;strictly serializable&quot;)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Catalog&lt;&#x2F;code&gt;: You can somewhat interchangeably use this with &lt;code&gt;Schema&lt;&#x2F;code&gt;, as it&#x27;s generally referring to an internal representation of the database system&#x27;s in-memory schema. E.g. the Binding phase resolves identifiers to columns&#x2F;tables using the Schema or Catalog.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Predicate&lt;&#x2F;code&gt;: This is typically referring to the &lt;code&gt;WHERE&lt;&#x2F;code&gt; clause of a query, essentially meaning the constraints we are putting on our query which will filter the resulting output.
In &lt;code&gt;SELECT * FROM t WHERE a = 7&lt;&#x2F;code&gt;: &lt;code&gt;t.a = 7&lt;&#x2F;code&gt; is our predicate.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Push-Down&lt;&#x2F;code&gt; or &lt;code&gt;Predicate Push-Down&lt;&#x2F;code&gt;: This is referring to applying a predicate (meaning essentially: filtering the resulting output) at a lower layer...
Now this one is going to seem incredibly obvious, but let&#x27;s imagine this query:&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; users u&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; orders o &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; u.id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; o.user_id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; u.last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;#39;Peters&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now theoretically we could:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Read all rows from users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Join them with all rows from orders&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Filter the result where last_name = &amp;#39;Peters&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This obviously works but is very dumb, because we are joining a ton of rows that we are just immediately throwing away.&lt;&#x2F;p&gt;
&lt;p&gt;A better plan is:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Use the predicate last_name = &amp;#39;Peters&amp;#39; while reading users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Only keep matching rows&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Join those rows with orders&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is called predicate pushdown, because we pushed the filter down closer to the data source.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Checkpointing&lt;&#x2F;code&gt;: The process of updating the actual database files with data from transactions which were written to the Write-Ahead-Log. This is typically done when the WAL reaches a certain size, or can be done manually, usually with a PRAGMA command.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;MVCC&lt;&#x2F;code&gt; (Multi-Version Concurrency Control): A technique used by many databases to allow multiple transactions to run at the same time. Instead of overwriting rows, the database keeps multiple versions so that each transaction can see the correct snapshot.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;Selectivity&lt;&#x2F;code&gt;: How many rows a predicate is expected to match, relative to the total number of rows in the table.&lt;&#x2F;p&gt;
&lt;p&gt;For example, if a table has 1,000,000 rows:&lt;&#x2F;p&gt;
&lt;p&gt;WHERE id = 5&lt;&#x2F;p&gt;
&lt;p&gt;is very selective, because it will probably return 1 row.&lt;&#x2F;p&gt;
&lt;p&gt;WHERE is_active = true&lt;&#x2F;p&gt;
&lt;p&gt;is not very selective, because it might return half the table.&lt;&#x2F;p&gt;
&lt;p&gt;Selectivity is extremely important for the query planner, because it helps decide things like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Should we use an index or do a scan?&lt;&#x2F;li&gt;
&lt;li&gt;Which table should we read first in a join?&lt;&#x2F;li&gt;
&lt;li&gt;Which join order will be fastest?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In general:
High selectivity = few rows = good for index lookups&lt;br &#x2F;&gt;
Low selectivity = many rows = scan might be faster*&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;the-life-cycle-of-a-sql-query&quot;&gt;The life-cycle of a SQL query:&lt;&#x2F;h3&gt;
&lt;p&gt;What happens under the hood when you execute a query?&lt;&#x2F;p&gt;
&lt;ol start=&quot;0&quot;&gt;
&lt;li&gt;
&lt;p&gt;Startup: when our database system first starts up, it must load the current Schema|Catalog into memory. All this information&#x2F;metadata is all just tables reserved for internal use, which describe the state of the database (all the tables, indexes, views, sequences). There is typically either a header on the first page of each file, or a dedicated file, which stores DB specific metadata such as PRAGMA values, settings, ANALYZE information, etc.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Parser: the string is ran through a SQL parser, which transforms the raw string&#x2F;text into an AST, which we will use directly in our database system. For each type of &lt;code&gt;ast::Statement&lt;&#x2F;code&gt;, we have some function which takes each statement node variant, and builds a query plan based it after traversing it, and sometimes rewriting parts of it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Binding: as described above, the AST is rewritten to include Schema&#x2F;Catalog aware nodes... In addition to rejecting any queries which might reference invalid&#x2F;nonexistent tables&#x2F;columns, because the AST is traversed in this step, some systems might also try to evaluate any constant expressions&#x2F;optimize in this step as well, e.g. by replacing stuff like &lt;code&gt;(12 * 12)&lt;&#x2F;code&gt; with &lt;code&gt;(144)&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Query planning: Now that we have an AST which is actually useful to us, we need to figure out how we will execute it.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Example query: &lt;code&gt;SELECT a, b from t WHERE a BETWEEN 1 and 100;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Essentially, the way we need to think about executing queries: is we pretty much need to imagine that the underlying table has like a billion+ rows (obviously not always, and often times we may actually know roughly many rows each table has). What I mean by this, is that we always want to avoid doing the dumbest thing... Which in this case would be:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1. Open table `t`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2. Go row-by-row, check the value of `a`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    If `a &amp;gt;= 1` &amp;amp;&amp;amp; `a &amp;lt;= 100`: output the row&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;3. Close table `t`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That is definitely the most straight forward thing to do... But what if there is an index on &lt;code&gt;a&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;Well let&#x27;s think about what this means, and what is an index, really? We might already know that indexes make lookups faster, but &lt;em&gt;why&lt;&#x2F;em&gt; and &lt;em&gt;how&lt;&#x2F;em&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;First: Do you know &lt;em&gt;why&lt;&#x2F;em&gt; our first example is the &quot;dumb&quot; thing to do?... Well as you probably guessed, it&#x27;s because &lt;code&gt;a&lt;&#x2F;code&gt; is not going to be in sorted order, so we cannot simply skip directly to the values which are &amp;gt;= 1 and then output rows, stopping when the value of &lt;code&gt;a&lt;&#x2F;code&gt; is &amp;gt; 100, so we &lt;em&gt;have&lt;&#x2F;em&gt; to check &lt;em&gt;all&lt;&#x2F;em&gt; the tuples in the entire table to guarantee that we return all values which satisfy our predicate.&lt;&#x2F;p&gt;
&lt;p&gt;Lets imagine we have an index on &lt;code&gt;users.last_name&lt;&#x2F;code&gt;... We want to return all users whose last_name = &#x27;Peters&#x27;. So instead of scanning the entire table, we can do a faster Seek on the index and then use the RowID&#x27;s from any matching index values... That allows us to then do a Seek on the &lt;code&gt;users&lt;&#x2F;code&gt; table directly because we now have the sorted value (the RowID or PRIMARY KEY). Any time we have the PRIMARY KEY or sometimes called the &quot;RowID alias&quot; in our predicate, this allows us to use a Seek operation instead of a scan.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;index_rowid_pages_diagram.svg&quot; &#x2F;&gt;
&lt;p&gt;The Index Seek then becomes our &lt;em&gt;access method&lt;&#x2F;em&gt; for our &lt;code&gt;users&lt;&#x2F;code&gt; table on this query.&lt;&#x2F;p&gt;
&lt;p&gt;*NOTE: Above, in our explanation of &lt;em&gt;Selectivity&lt;&#x2F;em&gt;, we said this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;In general:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;High selectivity = few rows = good for index lookups  &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Low selectivity = many rows = scan might be faster*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;How&#x2F;why could a &lt;em&gt;scan&lt;&#x2F;em&gt; be faster?&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Think about it for a minute and see if you can guess...&lt;&#x2F;p&gt;
&lt;p&gt;The reason is because every time you find a matching row while searching your index, you now have to grab the RowID and then do an additional Seek into the underlying table to fetch the actual result column values. This is why not all index lookups are actually faster, if the predicate is determined to have very low selectivity, it often can make more sense to just do a full scan of the table, because you no longer are having to jump around between several B+Trees&#x2F;data structures to fetch all the needed values.&lt;&#x2F;p&gt;
&lt;p&gt;But let&#x27;s say we have an index on &lt;code&gt;(a, b)&lt;&#x2F;code&gt; and the query is &lt;code&gt;SELECT a, b FROM t WHERE a &amp;gt; 100;&lt;&#x2F;code&gt;... Now our index contains &lt;em&gt;both&lt;&#x2F;em&gt; the values we need to satisfy the query. This is what&#x27;s known as a &lt;em&gt;Covering&lt;&#x2F;em&gt; index, and this is an extremely ideal situation in query planning. No extra Row ID Seek is needed to fetch the underlying row, you simply Seek to the index and return the values while they match.&lt;&#x2F;p&gt;
&lt;p&gt;So what if we have a join in our query?&lt;&#x2F;p&gt;
&lt;p&gt;Example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; users u&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; orders o &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; u.id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; o.user_id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; u.last_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;#39;Peters&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now things get more complicated, because we are no longer just choosing an access method for one table… we also need to decide:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Which table do we read first?&lt;&#x2F;li&gt;
&lt;li&gt;What access method do we use for each table?&lt;&#x2F;li&gt;
&lt;li&gt;In what order do we perform the joins?&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This is called selecting the &lt;strong&gt;join order&lt;&#x2F;strong&gt; and the &lt;strong&gt;access methods&lt;&#x2F;strong&gt;, and this is one of the primary and most difficult jobs of the query planner &#x2F; optimizer.&lt;&#x2F;p&gt;
&lt;p&gt;We could execute this query in several different ways.&lt;&#x2F;p&gt;
&lt;p&gt;One possible plan:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1. Scan users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2. For each user, lookup matching rows in orders&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another possible plan:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1. Use index on users.last_name to find &amp;#39;Peters&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2. For each matching user, lookup orders by user_id&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another possible plan:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;1. Scan orders&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;2. For each order, lookup user by primary key (RowID)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;All of these are logically correct, but some of them might be &lt;strong&gt;1000x slower&lt;&#x2F;strong&gt; than others depending on how much data is in each table and what indexes exist.&lt;&#x2F;p&gt;
&lt;p&gt;This is why the optimizer must estimate things like:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;How many rows are in each table&lt;&#x2F;li&gt;
&lt;li&gt;How selective a predicate is&lt;&#x2F;li&gt;
&lt;li&gt;Whether an index can be used&lt;&#x2F;li&gt;
&lt;li&gt;How expensive each join order would be&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Even for a simple query with 3 tables, there may already be dozens of possible join orders. Choosing the correct one is one of the hardest parts of building a database system, Inthe general case, optimal join ordering is known to be NP-hard, which is why real databases rely on a mixture of heuristics and cost estimation.&lt;&#x2F;p&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Execution: now that we have chosen a query plan, we actually need to run it.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The query planner does not directly run the query... Instead, it produces some kind of internal representation of the plan, which is made up of &lt;strong&gt;operators&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can think of operators as small building blocks that each do one simple thing, for example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Scan operator -&amp;gt; reads rows from a table&lt;&#x2F;li&gt;
&lt;li&gt;Index seek operator -&amp;gt; looks up rows using an index&lt;&#x2F;li&gt;
&lt;li&gt;Filter operator -&amp;gt; applies the WHERE predicate&lt;&#x2F;li&gt;
&lt;li&gt;Join operator -&amp;gt; combines rows from two tables&lt;&#x2F;li&gt;
&lt;li&gt;Sort operator -&amp;gt; orders rows&lt;&#x2F;li&gt;
&lt;li&gt;Aggregate operator -&amp;gt; computes things like COUNT &#x2F; SUM &#x2F; GROUP BY&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;A query plan is basically a tree of these operators.&lt;&#x2F;p&gt;
&lt;p&gt;For example, a simple query like:&lt;&#x2F;p&gt;
&lt;p&gt;SELECT *
FROM users
WHERE last_name = &#x27;Peters&#x27;;&lt;&#x2F;p&gt;
&lt;p&gt;might turn into a plan like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Filter(last_name = &amp;#39;Peters&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    IndexSeek(users_last_name_idx)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or for a join:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Join(users.id = orders.user_id)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    IndexSeek(users_last_name_idx)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Scan(orders)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Each operator produces rows, and passes them to the operator above it.&lt;&#x2F;p&gt;
&lt;p&gt;This means execution usually happens row-by-row, not all at once.&lt;&#x2F;p&gt;
&lt;p&gt;The scan reads a row →&lt;br &#x2F;&gt;
the filter checks it →&lt;br &#x2F;&gt;
the join combines it →&lt;br &#x2F;&gt;
the result is returned.&lt;&#x2F;p&gt;
&lt;p&gt;Some databases compile either the AST directly, or the query plan into bytecode, which is stepped through by a virtual machine (SQLite and tursodb). Many execute the plan using an iterator-style execution engine (like Postgres), and some might even generate native code (I believe some OLAP engines do this).&lt;&#x2F;p&gt;
&lt;p&gt;But the idea is generally the same: The planner decides &lt;em&gt;what to do&lt;&#x2F;em&gt; and the execution engine actually &lt;em&gt;does it&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;At some point during execution, the database actually needs to read and write data on disk, and this is handled by the &lt;strong&gt;storage engine&lt;&#x2F;strong&gt;. Most relational databases store tables and indexes using B-Trees (usually B+Trees, but it varies), which organize rows into fixed-size blocks called &lt;strong&gt;pages&lt;&#x2F;strong&gt; (often 4KB–16KB each). The database never reads a single row directly from disk, it always reads at least one entire page at a time.&lt;&#x2F;p&gt;
&lt;p&gt;A component, often called the &lt;em&gt;Pager&lt;&#x2F;em&gt; or &lt;em&gt;Buffer Pool manager&lt;&#x2F;em&gt; (names vary by database), is responsible for loading these pages from disk, writing them back when they change, and then keeping track of which pages are currently in memory. Since disk access is &lt;em&gt;extremely&lt;&#x2F;em&gt; slow compared to RAM, the database system keeps a &lt;strong&gt;page cache&lt;&#x2F;strong&gt;, which stores these recently used pages in memory. A huge part of database performance is just managing this cache correctly: deciding which pages to keep, which to evict, and when they need to be flushed back to disk.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-rows-are-actually-stored-on-disk&quot;&gt;How rows are actually stored on disk&lt;&#x2F;h3&gt;
&lt;p&gt;Earlier we mentioned that tables and indexes are stored using B-Trees, and that the database reads and writes fixed-size pages instead of individual rows. Let&#x27;s go a little deeper into what that actually means.&lt;&#x2F;p&gt;
&lt;p&gt;Each table is usually stored as a B+Tree, where each node of the tree is one page on disk. The pages at the bottom of the tree (called leaf pages) contain the actual rows, while the pages above them contain keys that help the database find the correct leaf page quickly. In fact if we &lt;code&gt;SELECT&lt;&#x2F;code&gt; some metadata about tables in SQLite: we can see that for each table in the Catalog, we store the &quot;root page&quot; of the table: &lt;img alt=&quot;root page&quot; src=&quot;&#x2F;rootpage.png&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Inside a page, rows are not just stored one after another in an array type of situation... The page has a small header and a list of pointers (often called slots or cell pointers), and then the actual row data somewhere else in the page. This makes it possible to insert and delete rows without having to rewrite the entire page every time.&lt;&#x2F;p&gt;
&lt;p&gt;When the database wants to read rows from a table, it uses something usually called a &lt;strong&gt;cursor&lt;&#x2F;strong&gt;. A cursor is basically an object that remembers where we currently are in a given B-Tree. It knows which page we are on, which slot inside the page we are looking at, and how to move to the next or previous row.&lt;&#x2F;p&gt;
&lt;p&gt;To find a specific row, the database starts at the root of the B-Tree, compares keys, follows pointers down through the internal pages, and eventually reaches the correct leaf page. Once it is on the leaf page, the cursor can move from row to row without having to search the tree again.&lt;&#x2F;p&gt;
&lt;p&gt;Indexes work the same way (at least B+Tree indexes do... There are other forms of indexes, primarily hash table indexes but we will leave that out for now), except as we stated earlier, instead of storing the full row they usually store the indexed value alongside a reference to the row in the table (often the RowID or primary key).&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes a row is too large to fit entirely inside one page. In that case, the database stores part of the row on the page and the rest in one or more &lt;strong&gt;overflow pages&lt;&#x2F;strong&gt;. The main page contains a pointer to the overflow pages, and the storage engine follows those pointers to read the full value. This is commonly used for large text or blob values.&lt;&#x2F;p&gt;
&lt;p&gt;Writing rows works by finding the correct leaf page using the B-Tree, modifying the page in memory, and then marking it &#x27;dirty&#x27; in the page cache. The pager later can write the updated page back to disk (usually through the WAL first, if the database is using one).&lt;&#x2F;p&gt;
&lt;p&gt;All of this might sound complicated (and I assure you, it is..), but at least the important idea is fairly simple:&lt;&#x2F;p&gt;
&lt;p&gt;Rows live on pages, the pages live in B-Trees and we use cursors to walk the tree to find the rows... So above, (in the simplest possible terms) when we say that we need to fetch rows from the underlying table, what we mean is we create a new BTree Cursor, and our pager will know from the root page, which page (and the page can just be an offset into a database file) to fetch from the pager, and then we follow pointers from there to possibly fetch other pages and then eventually read the tuples on those pages.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;btree.svg&quot; &gt;
&lt;p&gt;===============================&lt;&#x2F;p&gt;
&lt;p&gt;I hope this is helpful to someone out there, I tried to compile a list of things I wish I would have known at the very beginning of my journey. Maybe I will do a part 2 at some point. If you have any suggestions for improvements or comments, feel free to reach out on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;pthorpe92&quot;&gt;X&lt;&#x2F;a&gt; or by &lt;a href=&quot;mailto:preston@pthorpe92.dev&quot;&gt;email&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>You can do better</title>
          <pubDate>Fri, 13 Mar 2026 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/better/</link>
          <guid>https://pthorpe92.dev/better/</guid>
          <description xml:base="https://pthorpe92.dev/better/">&lt;h2 id=&quot;lately-on-x&quot;&gt;Lately on X&lt;&#x2F;h2&gt;
&lt;p&gt;I have noticed a trend of posts that I imagine are probably the natural response to &#x27;LinkedIn-brain&#x27; posts, which might be the result of the poor job market right now:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;&quot;If hard work paid off, the donkey would own the farm&quot;&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And if you were to come straight from the slop filled cringe fest that is LinkedIn these days, I can totally understand why you might have this attitude... But I can&#x27;t help but find myself wanting to tweet about this, before realizing that I don&#x27;t pay for more than 160 characters. This is why I have decided to write a quick blog post about it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-argument-for-working-hard&quot;&gt;The argument for working hard&lt;&#x2F;h2&gt;
&lt;p&gt;Instead of saying some generic motivational jargon, I&#x27;ll try to give you a few examples and explain specifically what I mean.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Let&#x27;s say you work on a team&lt;&#x2F;strong&gt;, and your job generally consists of working on tickets that are assigned to you, and you spend some time every day pushing PR&#x27;s that get reviewed by others and your time is allotted by them: You notice that your CI runs take ~25-30 mins each, and this is mildly annoying but definitely something every developer notices, but nothing anyone does anything about.&lt;&#x2F;p&gt;
&lt;p&gt;When you look at the DAG, you notice that there is no cacheing of build artifacts or dependencies and all your jobs are running serially.&lt;&#x2F;p&gt;
&lt;p&gt;You could spend the ~1hr or so setting up sccache and matrix runners so everything runs in parallel and cuts your CI&#x2F;CD build and deployment pipeline down to ~3-4 mins, or you could just mind your business and only do what is assigned to you... Maybe someone will think of that, and make a Jira ticket for you to pick up one day.&lt;&#x2F;p&gt;
&lt;p&gt;But if you go out of your way to fix this on your own, every single person on the team, without a doubt, will notice that their build times got cut by 80% and their dev experience improved.&lt;&#x2F;p&gt;
&lt;p&gt;Now you repeat this behavior over the course of a couple years, and it&#x27;s time for some layoffs at your company. Seems a lot less likely they are going to choose you, if you spent your time making objectively beneficial decisions for the team, instead of only focusing on what you were tasked with doing.&lt;&#x2F;p&gt;
&lt;p&gt;Same idea when you come up for a promotion or a raise... EVERYONE notices this, and choosing to go above and beyond makes you a better teammate, who others will want to work with.&lt;&#x2F;p&gt;
&lt;p&gt;Take initiative on your own. Often times we developers are the &#x27;boots on the ground&#x27; and have insight into things like cloud cost savings, potential productivity increases and workflow improvements that PM&#x27;s and admin won&#x27;t. In a world where we LLM&#x27;s are becoming what seems like a threat to this kind of work, don&#x27;t be ashamed of separating yourself from others by taking initiative and providing value to your team and your company.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m not saying you have to work 9-9-6 and have no social life, I&#x27;m just saying that it&#x27;s rewarding to take personal responsibility and ownership over the products you ship and the things you work on. There is absolutely nothing wrong with working hard and taking pride in what you do.&lt;&#x2F;p&gt;
&lt;p&gt;Thank you for your attention to this matter.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;P&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Rewriting SQLite: Adding a new join algorithm</title>
          <pubDate>Sat, 22 Nov 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/hash-joins/</link>
          <guid>https://pthorpe92.dev/hash-joins/</guid>
          <description xml:base="https://pthorpe92.dev/hash-joins/">&lt;h1 id=&quot;i-am-not-sure-that-there-exists-a-group-of-bigger-sqlite-nerds-than-those-of-us-at-turso&quot;&gt;I am not sure that there exists a group of bigger SQLite nerds than those of us at Turso.&lt;&#x2F;h1&gt;
&lt;p&gt;We use SQLite for &lt;em&gt;everything&lt;&#x2F;em&gt;.. Including for OLAP workloads where we should be using &lt;code&gt;duckdb&lt;&#x2F;code&gt;, or for services which we would &lt;em&gt;love&lt;&#x2F;em&gt; to be totally stateless pods,
instead we have statefulsets and PVC&#x27;s with EBS volumes containing SQLite .db files. Every one of us has probably read just about the entire 265k LOC amalgamation
sqlite3.c source file more than once all the way through.&lt;&#x2F;p&gt;
&lt;p&gt;So if anyone has an insight into some of the pain points that will arise from using SQLite in production, surely we are at least good candidates.&lt;&#x2F;p&gt;
&lt;p&gt;But if you ask most Database nerds, what the fundamental limitations are of SQLite, I would guess that almost all will mention at least one of the following:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Exclusive write lock.&lt;&#x2F;p&gt;
&lt;p&gt;The architecture and design around how SQLite manages transaction isolation, as well as their journaling design (which we will cover a bit in #2 as well),
means that the &lt;code&gt;writer&lt;&#x2F;code&gt; lock is exclusive and no two connections can obtain a write transaction concurrently. (This is something that &lt;code&gt;tursodb&lt;&#x2F;code&gt; is attempting to fix
with MVCC mode.)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Write performance.&lt;&#x2F;p&gt;
&lt;p&gt;At least in WAL mode, SQLite appends all (usually 4kb) pages that are touched as part of a write transaction, referred to as WAL frames, to the log... This includes
any and all pages which are shuffled around due to B-Tree balancing, so in theory an INSERT of just a single byte could cause many 4kb pages to be written to the log.
Also, when checkpointing (moving these frames from the log to the DB file), SQLite does not use any cached pages it might already have in-memory, it reads each page from disk
during the backfilling process and performs N 4kb reads and N 4kb writes where N is the total number of frames needing backfilling. This can cause substantial write
amplification and is known to be problematic for write-heavy workloads. For applications which are even moderately write-heavy, which are not gracefully shutting down periodically, typically you have to setup some kind of a background process which monitors the WAL size and periodically forcing a blocking TRUNCATE checkpoint due to the possibility of the WAL growing unbounded.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Checksum&#x2F;integrity verification.&lt;&#x2F;p&gt;
&lt;p&gt;See this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;avi.im&#x2F;blag&#x2F;2025&#x2F;sqlite-wal-checksum&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt; for more details&lt;&#x2F;p&gt;
&lt;p&gt;tl;dr SQLite can &#x27;silently&#x27; allow corruption and the user will not find out till much later on.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Read performance for any OLAP style queries.&lt;&#x2F;p&gt;
&lt;p&gt;SQLite’s query engine is extremely good for what it is but its physical join toolbox is intentionally small. By design, SQLite relies on nested loop joins as the core join strategy.
That choice keeps the planner simple and predictable, but it comes with some hard ceilings once you push into any analytic-style workloads.
This is what we will be talking about today in this blog post.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;join-algorithms-a-brief-tour&quot;&gt;Join Algorithms: A Brief Tour&lt;&#x2F;h2&gt;
&lt;p&gt;Most databases implement a small family of join algorithms:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Nested Loop Join (NLJ):
&lt;br &#x2F;&gt;
The simplest: iterate over table A and, for each row, search for matches in table B.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Merge Join:
&lt;br &#x2F;&gt;
Requires both inputs to be ordered on the join key. Walk them together like merging two sorted lists.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Hash Join:
&lt;br &#x2F;&gt;
Build an in-memory hash table of one input keyed by the join column(s), then probe it with rows from the other input.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;There are lots of refinements (index nested loops, block nested loops, hybrid&#x2F;grace hash joins, etc.), but almost everything is a variant of these.&lt;&#x2F;p&gt;
&lt;p&gt;SQLite fundamentally lives in the NLJ world, making some optimizations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;how-nested-loop-joins-work-and-how-sqlite-makes-them-fast&quot;&gt;How Nested Loop Joins Work (and how SQLite makes them fast)&lt;&#x2F;h3&gt;
&lt;p&gt;The nested loop join really is as simple as it sounds. The outer loop iterates over one table, and for each row, the inner loop searches the other for matches.&lt;&#x2F;p&gt;
&lt;p&gt;SQLite does add several layers of optimization on top of this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Using an index on the join column to avoid full scans of table B
(so the inner loop becomes an index lookup&#x2F;Seek rather than a linear scan).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Reordering tables to minimize work&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Automatic “ephemeral” indexes when no suitable index exists.
SQLite may build a temporary B-tree (we see &lt;code&gt;OpenAutoindex&lt;&#x2F;code&gt; in the plan) to avoid repeated full scans on the inner table.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In SQLite’s VDBE bytecode you can see the basic NLJ shape:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OpenRead cursor for employees&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OpenRead cursor for departments&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;For each row in employees (Rewind&#x2F;Next loop)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Seek into departments (using persistent or ephemeral index)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Check predicate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Emit result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Oversimplified pseudocode that includes an ephemeral index looks soemthing like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tempIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt; BTreeIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; rowA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; tableA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    tempIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;rowA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; rowA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;RowID&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; rowB&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; tableB&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rowID&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; tempIndex&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;get&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;rowB&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; rowID&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; is not&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        rowA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; tableA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;seek&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;rowID&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;&quot;&gt;        output&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;rowA&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; rowB&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This works extremely well for small datasets or OLTP-style queries where joins are selective and tables are modest in size.
(NOTE: SQLite will sometimes also build a bloom filter as a further optimization, so this can be probed to determine whether or not a Seek
should even be done on that join key in the inner loop, but because &lt;code&gt;tursodb&lt;&#x2F;code&gt; does not yet implement this optimization we will pretty much omit this for now)&lt;&#x2F;p&gt;
&lt;p&gt;It also works &lt;em&gt;surprisingly&lt;&#x2F;em&gt; well for a lot of medium-sized workloads, which is why SQLite has done so well with only NLJ.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-can-we-improve-on-these-optimizations&quot;&gt;How can we improve on these optimizations.&lt;&#x2F;h2&gt;
&lt;p&gt;For our first improvement, let&#x27;s consider the following:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; *&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; large_table_1 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; large_table_2 &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; substr(a.category, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; substr(b.category, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Logically this is an equality join, but it’s on expressions rather than raw columns. If there is no index specifically on &lt;code&gt;substr(b.category, 1, 3)&lt;&#x2F;code&gt;,&lt;&#x2F;p&gt;
&lt;p&gt;SQLite&#x27;s query planner has a much harder time constructing an efficient ephemeral index here, so it likely will be a full naive nested loop with scans.&lt;&#x2F;p&gt;
&lt;p&gt;If both tables have million+ rows, it can very quickly turn into tens of billions of comparisons and page touches, even if the page cache saves from reading everything from disk each time.&lt;&#x2F;p&gt;
&lt;p&gt;So overall, ideally we would like to improve on this in two different places:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Use a more performant data structure, to improve on the O(log n) insert&#x2F;seeks for each outer table row.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Improve the query planner to properly use non &#x27;plain column&#x27; expressions as part of our equijoin predicate,
and try our best not to fall back to nested scans.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h1 id=&quot;behold-the-hash-join&quot;&gt;Behold the hash join:&lt;&#x2F;h1&gt;
&lt;p&gt;With a similar plan as using an ephemeral index, we can instead use a hash table to get near constant time lookups, at the cost of some additional memory and CPU cycles for hashing.&lt;&#x2F;p&gt;
&lt;p&gt;The general idea is to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Choose one table as the build input (preferably the smaller one).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Make a single pass over it, building an in-memory hash table keyed by the join column(s).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Then scan the larger probe input, and for each row, do a ~constant-time hash lookup.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If we can choose a hash function that will perform well and avoid collisions as much as possible, we can get fast hashing speed and near O(1) lookups when probing. We can either store the
materialized values directly in the hash table, or for more complex&#x2F;fallback scenarios we can store the rowID of the underlying row, along with the join key (for that case, will cost an additional SeekRowID when a probe matches) and we are able to emit or use the result columns.&lt;&#x2F;p&gt;
&lt;p&gt;The crucial differences vs an ephemeral B-tree:&lt;&#x2F;p&gt;
&lt;p&gt;lookups are ~O(1) instead of O(log N), inserts should be cheaper because they don&#x27;t require &lt;code&gt;MakeRecord&lt;&#x2F;code&gt; opcode to build the index record with the join key,
which in the case of the ephemeral index needs to be saved to compare directly to the probe key, along with the underlying rowid. Also for the common case where
we cache the row&#x27;s payload, we are also saving the additional BTree seek required to fetch the result columns from the row itself, we can store them during the build
phase and get the purely constant time lookup.&lt;&#x2F;p&gt;
&lt;p&gt;the hash table is structurally more amenable to optimizations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;partitioning&lt;&#x2F;li&gt;
&lt;li&gt;spilling individual partitions to disk(grace&#x2F;hybrid hash join)&lt;&#x2F;li&gt;
&lt;li&gt;eventually things like parallelizing build&#x2F;probe, vectorizing probes, etc.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;We think we could improve on the default SQLite features by adding hash joins to &lt;code&gt;tursodb&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;implementing-hash-joins-in-tursodb&quot;&gt;Implementing Hash joins in tursodb&lt;&#x2F;h1&gt;
&lt;p&gt;Because SQLite (and so of course, tursodb) is implemented as essentially a virtual machine with a storage engine attached, and query plans are just emitted bytecode, adding a new join
algorithm will need to consist of creating new Opcodes which we emit at plan time and will be stepped through at runtime and executed by the VDBE (Virtual database engine).&lt;&#x2F;p&gt;
&lt;p&gt;So we are going to need Opcodes to:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;HashBuild - feed a build-side row into the hash table.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;HashBuildFinalize - finalize the build, potentially spilling partitions.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;HashProbe - hash and probe a key, yielding the build-side rowid(s).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;HashNext - iterate through additional matches in the same bucket.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;HashClose - free the hash table.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Instead of simply using a different data structure for the join, we will also make an attempt to improve the optimizer&#x2F;query planner.&lt;&#x2F;p&gt;
&lt;p&gt;Remember the example query:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt; users.first_name, products.id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; users &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt; products &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; substr(users.first_name,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; substr(products.name, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Because neither side of the binary equality expression is a plain Column, and in this case both are expressions, the ast looks something like:
&lt;br &#x2F;&gt;
&lt;code&gt;BinaryExpression{lhs: Expr::Function, operator: Operator::Eq, rhs: Expr::Function}&lt;&#x2F;code&gt;
&lt;br &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;br &#x2F;&gt;
We know SQLite actually will not build an ephemeral index for this query, instead it will fall back to the most naive nested loop join with a full O(n * m)
scan. We will improve on this by walking the expressions and tracking the indices into them for each expression that matches the `build` and `probe` tables,
this way we can determine that for the following:
&lt;br &#x2F;&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashJoinOp&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Index of the build table in the join order&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; build_table_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Index of the probe table in the join order&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; probe_table_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Join key references, each entry points to an equality condition in the [WhereTerm]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; and indicates which side of the equality belongs to the build table.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; join_keys&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;HashJoinKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Memory budget for hash table (used for cost based optimizations)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; mem_budget&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashJoinKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Index into the predicate array&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; where_clause_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Which side of the binary equality expression belongs to the build table.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; The other side implicitly belongs to the probe table, because we will only&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; ever select equijoin conditions for hash joins.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; build_side&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; BinaryExprSide&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The expression will look something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt;ast&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;BinaryExpression&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    lhs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Substr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt;ast&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Column&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;users&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;first_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;},&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    operator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Operator&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Eq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rhs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Expr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Substr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt;ast&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Column&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;products&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}] }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We would walk the ast::Expr, and track that &lt;code&gt;build_side&lt;&#x2F;code&gt; has &lt;code&gt;BinaryExprSide::Left&lt;&#x2F;code&gt; since we are going to use &lt;code&gt;users&lt;&#x2F;code&gt; as the build table, then given the
predicate we will be able to translate the expression itself and load the value from the output register directly into the hash table, so the resulting value is hashed
and the probe side expression can be compared against it.&lt;&#x2F;p&gt;
&lt;p&gt;Otherwise, we would simply be calling &lt;code&gt;emit_column_or_rowid&lt;&#x2F;code&gt; directly, and instead tracking the column index.. Here we are tracking the &lt;code&gt;expr&lt;&#x2F;code&gt; index and calling &lt;code&gt;translate_expr&lt;&#x2F;code&gt;
into the resulting register.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;-- simplified&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;addr  opcode             p1    p2    p3  p4        p5  comment&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;----  -----------------  ----  ----  --  --------- --  -------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;     OpenRead           &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0     2     0             0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;   table&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;users, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;root&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;, iDb&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;     OpenRead           &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1     3     0             0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;   table&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;products, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;root&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span&gt;, iDb&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;     Rewind&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;             0     8     0             0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;   Rewind table&lt;&#x2F;span&gt;&lt;span&gt; users&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span&gt;       Column           &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0     1     5             0&lt;&#x2F;span&gt;&lt;span&gt;   r[5]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;users.first_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;       Function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;         0     5     4&lt;&#x2F;span&gt;&lt;span&gt;   substr    &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;   r[4]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;func(r[5..7]) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;-- evaluate the function with the col argument -&amp;gt; HashBuild&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span&gt;       HashBuild        &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0     4     1             0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;     Next&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;               0     4     0             0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span&gt;     HashBuildFinalize  &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3     0     0             0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;     Rewind&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;             1     20    0             0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;   Rewind table&lt;&#x2F;span&gt;&lt;span&gt; products&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span&gt;      Column           &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1     1     9             0&lt;&#x2F;span&gt;&lt;span&gt;   r[9]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;products.name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;11&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;      Function&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;         0     9     8&lt;&#x2F;span&gt;&lt;span&gt;   substr    &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;   r[8]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;func(r[9..11])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span&gt;      HashProbe        &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3     8     1&lt;&#x2F;span&gt;&lt;span&gt;   r[12]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;19  0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span&gt;      SeekRowid        &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0     12    19            0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;   if&lt;&#x2F;span&gt;&lt;span&gt; (r[12]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;!=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;cursor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; for table&lt;&#x2F;span&gt;&lt;span&gt; users.rowid) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;goto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 19&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;14&lt;&#x2F;span&gt;&lt;span&gt;      Column           &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0     1     1             0&lt;&#x2F;span&gt;&lt;span&gt;   r[1]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;users.first_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;15&lt;&#x2F;span&gt;&lt;span&gt;      RowId            &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1     2     0             0&lt;&#x2F;span&gt;&lt;span&gt;   r[2]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;products.rowid&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;16&lt;&#x2F;span&gt;&lt;span&gt;      ResultRow        &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1     2     0             0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;   output&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt;r[1..2]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;17&lt;&#x2F;span&gt;&lt;span&gt;      HashNext         &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3     12    19            0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;18&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;      Goto&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;             0     13    0             0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;19&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    Next&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;               1     10    0             0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;20&lt;&#x2F;span&gt;&lt;span&gt;    HashClose          &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3     0     0             0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;21&lt;&#x2F;span&gt;&lt;span&gt;    Halt               &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0     0     0             0&lt;&#x2F;span&gt;&lt;span&gt;   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The fun part is of course inside HashBuild &#x2F; HashBuildFinalize &#x2F; HashProbe: the hash table implementation and how we make it safe for large joins.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;which-hash-function-should-we-use&quot;&gt;Which hash function should we use?&lt;&#x2F;h2&gt;
&lt;p&gt;After asking on &lt;code&gt;X&lt;&#x2F;code&gt;, I received some great suggestions from DB veterans, such as &lt;code&gt;XXHash&lt;&#x2F;code&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;_Felipe&quot;&gt;@_Felipe&lt;&#x2F;a&gt;), and &lt;code&gt;GxHash&lt;&#x2F;code&gt; or &lt;code&gt;rapidhash&lt;&#x2F;code&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;AlexMillerDB&quot;&gt;@AlexMillerDB&lt;&#x2F;a&gt;)
and went down the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rurban&#x2F;smhasher&quot;&gt;smhasher&lt;&#x2F;a&gt; rabbit hole, which is pretty much a one stop shop for comparing hash functions.&lt;&#x2F;p&gt;
&lt;p&gt;After a couple of naive benchmarks, I went with &lt;code&gt;rapidhash&lt;&#x2F;code&gt; for the MVP. In the future we may choose different
hash functions depending on the key type and size, but “one good, fast hash” gets us very far.&lt;&#x2F;p&gt;
&lt;p&gt;We also fold SQLite-style collations into the hash:&lt;&#x2F;p&gt;
&lt;p&gt;For COLLATE NOCASE text, we hash the to_lowercase() representation.&lt;&#x2F;p&gt;
&lt;p&gt;For COLLATE RTRIM, we trim trailing whitespace before hashing.&lt;&#x2F;p&gt;
&lt;p&gt;For BINARY we hash the raw bytes.&lt;&#x2F;p&gt;
&lt;p&gt;That way equality and hashing line up with the comparison rules the rest of the engine uses.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;spillin-making-hash-joins-behave-under-memory-pressure-the-hard-part&quot;&gt;Spillin’: making hash joins behave under memory pressure (the hard part).&lt;&#x2F;h2&gt;
&lt;p&gt;Hash tables are obviously very fast but they can also be incredibly memory-hungry. In a traditional RDBMS, the hash table lives inside the same buffer manager
that already knows how to spill to disk and re-read pages. Because SQLite doesn&#x27;t include the hash table in their toolbox, for tursodb, the hash join is an extra
piece of machinery, outside of the pager; so it would be very easy to accidentally blow through RAM on a big join if everything is naively kept in memory.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashTable&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; The hash buckets (used when not spilled).&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buckets&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;HashBucket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Number of entries in the table.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    num_entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Current memory usage in bytes.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mem_used&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Memory budget in bytes.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mem_budget&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Number of join keys.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    num_keys&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Collation sequences for each join key.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    collations&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;CollationSeq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Current state of the hash table.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashTableState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; IO object for disk operations.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    io&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; IO&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Current probe position bucket index.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    probe_bucket_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Current probe entry index within bucket.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    probe_entry_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Cached hash of current probe keys to avoid recomputing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    current_probe_hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Current probe key values being searched.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    current_probe_keys&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    spill_state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;SpillState&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; Index of current spilled partition being probed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    current_spill_partition_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashEntry&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; key_values&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; rowid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; For most cases, to avoid an additional SeekRowID&#x2F;btree seek on a match, we can&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F;&#x2F; pre-cache the needed result columns in the hash table directly.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span&gt; payload_values&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;derive&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Clone&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashBucket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    entries&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;HashEntry&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The hash table tracks:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;mem_used&lt;&#x2F;code&gt;: approximate bytes for all resident entries in memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;mem_budget&lt;&#x2F;code&gt;: a soft per-join limit (eventually will be configurable, but will start with 64 MiB by default in release builds).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;state&lt;&#x2F;code&gt;: Building, Probing, Spilled, Closed.&lt;&#x2F;p&gt;
&lt;p&gt;During the build phase:&lt;&#x2F;p&gt;
&lt;p&gt;We insert entries and increment &lt;code&gt;mem_used&lt;&#x2F;code&gt; by entry.size_bytes().&lt;&#x2F;p&gt;
&lt;p&gt;If &lt;code&gt;mem_used&lt;&#x2F;code&gt; + &lt;code&gt;entry_size&lt;&#x2F;code&gt; would exceed mem_budget, we:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Initialize a SpillState (if this is the first overflow).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Redistribute existing buckets into NUM_PARTITIONS in-memory partition buffers using the hash value.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Mark the table as Spilled.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Pick one or more partition buffers to spill entirely to disk, freeing their memory.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The spill path uses a very simple on-disk layout:&lt;&#x2F;p&gt;
&lt;p&gt;Each partition has one or more &lt;code&gt;SpillChunk{file_offset, size_bytes, num_entries}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Each entry is serialized as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[hash:8][rowid:8][num_keys:varint][key1_type:1][key1_len:varint][key1_data]...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We append a length-prefixed entry blob for each &lt;code&gt;HashEntry&lt;&#x2F;code&gt; in that partition.&lt;&#x2F;p&gt;
&lt;p&gt;After writing a partition:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;That partition’s buffer is cleared.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;mem_used&lt;&#x2F;code&gt; is reduced by the buffer’s &lt;code&gt;mem_used&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We remember the chunk metadata inside &lt;code&gt;SpilledPartition&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;At the end of the build phase, finalize_build does one more pass:&lt;&#x2F;p&gt;
&lt;p&gt;For partitions that have already spilled, any remaining entries are serialized and appended as new chunks.&lt;&#x2F;p&gt;
&lt;p&gt;For partitions that never spilled, we keep them purely in memory:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We consume their PartitionBuffer, build buckets, and mark them as PartitionState::InMemory.
&lt;ul&gt;
&lt;li&gt;These are always resident and only counted in mem_used (no disk chunks, no LRU).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;At that point we transition to Probing and the build side is “frozen”.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;hybrid-grace-hash-join-and-partition-reloading&quot;&gt;Hybrid Grace hash join and partition reloading.&lt;&#x2F;h3&gt;
&lt;p&gt;This algorithm behaves like a hybrid grace hash join, in that we do not hash&#x2F;partition both the build + probe tables.
We attempt to do the whole thing in memory, but if we do spill, than we begin to partition the table and spill only
the necessary partitions to disk.&lt;&#x2F;p&gt;
&lt;p&gt;Any partitions that we &lt;em&gt;did&lt;&#x2F;em&gt; have the memory budget for during build time are kept memory resident throughout
the entire join and only partitions which &lt;em&gt;did&lt;&#x2F;em&gt; spill are cycled to and from disk and tracked via LRU. We treat the &lt;code&gt;mem_limit&lt;&#x2F;code&gt; for the table as a
soft limit and simply try to avoid both drastically exceeding this limit, and thrashing of parititons to&#x2F;from disk.&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;hashtable.png&quot; style=&quot;width: 1024px&quot;&#x2F;&gt;
&lt;p&gt;&lt;strong&gt;Overview&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The hash function also determinus a partition index:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; partition_from_hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    ((&lt;&#x2F;span&gt;&lt;span&gt;hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; PARTITION_BITS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; as usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;NUM_PARTITIONS&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;For partitions that never spilled (PartitionState::InMemory):&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;There’s nothing special to do; they live in RAM for the lifetime of the join.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;For partitions that did spill:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;We only load them on demand when the probe hits that partition.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Loading is done via a re-entrant &lt;code&gt;load_spilled_partition(partition_idx)&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;p&gt;If the partition is OnDisk, we:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Schedule asynchronous reads for each SpillChunk (we use our own I&#x2F;O model with hand-rolled state machines and event loop, no async&#x2F;await).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Accumulate all bytes into a read_buffer.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Once all chunks are read, we parse them into HashEntrys and build buckets.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;We estimate the resident memory of those buckets and update accounting.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If the partition is already Loaded, we simply mark it as recently-used in an LRU.&lt;&#x2F;p&gt;
&lt;p&gt;If reads are still in flight, we return an &lt;code&gt;IOResult::IO&lt;&#x2F;code&gt; and the VM yields.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;keeping-probe-time-memory-under-control-and-avoiding-thrash&quot;&gt;Keeping probe-time memory under control (and avoiding thrash)&lt;&#x2F;h3&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; probe_partition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;    &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt; self&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;    partition_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;    probe_keys&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;HashEntry&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; hash_join_key&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;...&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; partition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; spill_state&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;find_partition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;partition_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; !&lt;&#x2F;span&gt;&lt;span&gt;partition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;is_loaded&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;() {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; bucket_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;hash&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; as usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; %&lt;&#x2F;span&gt;&lt;span&gt; partition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buckets&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; bucket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; = &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;partition&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;buckets&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;bucket_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;];&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; scan bucket entries, compare keys, emit matches&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we stopped here, probe-time behavior could still be ugly. Imagine the probe side alternates between two “cold” partitions:&lt;&#x2F;p&gt;
&lt;p&gt;We would repeatedly load partition A, then evict it and load B, then evict it and load A again, etc.&lt;&#x2F;p&gt;
&lt;p&gt;To keep things sane, the hash table maintains a small, in-memory LRU cache of loaded spilled partitions:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;loaded_partitions_lru&lt;&#x2F;em&gt;: &lt;code&gt;VecDeque&amp;lt;usize&amp;gt;&lt;&#x2F;code&gt; partition indices in LRU order.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;loaded_partitions_mem&lt;&#x2F;em&gt;: &lt;code&gt;usize&lt;&#x2F;code&gt; approximate memory used by the loaded spilled partitions’ buckets.&lt;&#x2F;p&gt;
&lt;p&gt;Important distinctions:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;mem_used&lt;&#x2F;code&gt; tracks the base in-memory footprint:&lt;&#x2F;p&gt;
&lt;p&gt;The original non-spilled buckets.&lt;&#x2F;p&gt;
&lt;p&gt;Any never-spilled partitions that were materialized in memory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;loaded_partitions_mem&lt;&#x2F;code&gt; tracks only the additional cost of bringing spilled partitions back into RAM.&lt;&#x2F;p&gt;
&lt;p&gt;When we load or parse a spilled partition, we estimate:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; partition_bucket_mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;buckets&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;HashBucket&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;])&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    buckets&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;size_bytes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;())&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And before committing to keeping it resident, we call:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;evict_partitions_to_fit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;resident_mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; protect_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;While mem_used + loaded_partitions_mem + incoming_mem &amp;gt; mem_budget:&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Picks the least-recently-used partition that is Loaded, and has backing spill chunks (!chunks.is_empty()).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Clears its buckets, resets it to OnDisk, and subtracts its resident_mem from loaded_partitions_mem.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Then we record the new resident partition:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;record_partition_resident&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;partition_idx&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; resident_mem&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which swaps in the new resident_mem value for that partition + adjusts &lt;code&gt;loaded_partitions_mem&lt;&#x2F;code&gt; and moves the partition to the back of the LRU as most-recently-used.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The effect in practice:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The hash join respects &lt;code&gt;mem_budget&lt;&#x2F;code&gt; during build (by spilling whole partitions).&lt;&#x2F;p&gt;
&lt;p&gt;During probe, it keeps at most a small working set of spilled partitions resident at once.&lt;&#x2F;p&gt;
&lt;p&gt;Typical workloads where only a few partitions are hot see greatly reduced thrash: once a partition is in the LRU, repeated probes for that partition reuse the same buckets.&lt;&#x2F;p&gt;
&lt;p&gt;Pathological workloads where the probe touches more distinct partitions than fit in memory still work; they just spill&#x2F;reload more often, but at least not entirely arbitrarily&#x2F;uncontrolled.
Eventually if necessary, we can improve on this algorithm further down the road, but when we have more metadata avialable and we are tracking things like
total size of each table, that will allow us to make better choices in the query planner, as even choosing the proper table for the &lt;code&gt;build&lt;&#x2F;code&gt; side makes a tremendous
difference in performance, as we could avoid spilling to disk entirely in many situations.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;when-does-the-planner-pick-a-hash-join&quot;&gt;When does the planner pick a hash join?&lt;&#x2F;h3&gt;
&lt;p&gt;Right now, tursodb is conservative:&lt;&#x2F;p&gt;
&lt;p&gt;We only consider hash joins for queries where SQLite would otherwise build an ephemeral index on the inner side of a nested loop.&lt;&#x2F;p&gt;
&lt;p&gt;We avoid hash joins when a good persistent index already exists and can be used directly, using a real index is &lt;em&gt;always&lt;&#x2F;em&gt; cheaper than building a hash table.&lt;&#x2F;p&gt;
&lt;p&gt;The planner will restrict choosing hashjoins only for INNER equijoins.&lt;&#x2F;p&gt;
&lt;p&gt;We must identify which side should be the build side (this is tough at the moment because we don&#x27;t track metadata about the size of tables).&lt;&#x2F;p&gt;
&lt;p&gt;Then we generate bytecode that materializes the build input by creating a loop of &lt;code&gt;Rewind&#x2F;HashBuild&#x2F;Next&lt;&#x2F;code&gt; for the build table, with any predicates needed from the
WHERE clause which might limit the amount of necessary rows needed to hash. (e.g. &lt;code&gt;SELECT t.a, t2.b FROM t JOIN t2 ON t2.c = t.c WHERE t.a &amp;gt; 100&lt;&#x2F;code&gt;, we only have
to hash the join keys for rows in t where a &amp;gt; 100), only if the build table is the only table reference in that particular predicate so we can mark it consumed.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;final-outcome&quot;&gt;Final outcome:&lt;&#x2F;h1&gt;
&lt;p&gt;At the risk of this blog post getting far too long, let&#x27;s look at the best case scenario with our improvements we have made:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;query&quot;&gt;Query:&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; users.first_name, products.id&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; FROM&lt;&#x2F;span&gt;&lt;span&gt; users &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; products &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;ON&lt;&#x2F;span&gt;&lt;span&gt; substr(users.first_name,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; substr(products.name, &lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No indexes&lt;br &#x2F;&gt;
15k rows per table&lt;&#x2F;p&gt;
&lt;p&gt;Times:&lt;br &#x2F;&gt;
SQLite: &lt;code&gt;22.772 seconds&lt;&#x2F;code&gt;  -- nested loop &lt;br &#x2F;&gt;
tursodb: &lt;code&gt;2.334 seconds&lt;&#x2F;code&gt;  -- hash join&lt;&#x2F;p&gt;
&lt;p&gt;Because SQLite doesn&#x27;t create an ephemeral btree index here, we are able to get 10x speedup on this query (and we would likely have been able to get similar speedup by just
improving the planner and choosing to still build btree index with two expressions).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;And a much more fair comparison:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;query-1&quot;&gt;Query:&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt; users.first_name, products.name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; from&lt;&#x2F;span&gt;&lt;span&gt; users &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;join&lt;&#x2F;span&gt;&lt;span&gt; products &lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt; products.name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; users.first_name;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No indexes &lt;br &#x2F;&gt;
15k rows per table&lt;&#x2F;p&gt;
&lt;p&gt;Times:
SQLite: &lt;code&gt;20ms&lt;&#x2F;code&gt;  -- ephemeral index &lt;br &#x2F;&gt;
tursodb: &lt;code&gt;15ms&lt;&#x2F;code&gt; -- hash join&lt;&#x2F;p&gt;
&lt;p&gt;You can check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tursodatabase&#x2F;turso&#x2F;pull&#x2F;4063&quot;&gt;PR here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading! If you are interested or a fellow database&#x2F;systems nerd, stop by the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tursodatabase&#x2F;turso&quot;&gt;repo&lt;&#x2F;a&gt; or the discord, and join our open source community.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Checkpointing performance in Write-Ahead-Logs</title>
          <pubDate>Wed, 13 Aug 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/wal-checkpoint-performance/</link>
          <guid>https://pthorpe92.dev/wal-checkpoint-performance/</guid>
          <description xml:base="https://pthorpe92.dev/wal-checkpoint-performance/">&lt;h3 id=&quot;making-checkpointing-fast&quot;&gt;Making Checkpointing fast&lt;&#x2F;h3&gt;
&lt;p&gt;Since I began working for turso officially in May of this year (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;turso.tech&#x2F;blog&#x2F;working-on-databases-from-prison&quot;&gt;relevant post&lt;&#x2F;a&gt;), I had been spending most of my time learning the inner workings of the cloud platform, and familiarizing myself with the other codebases and libraries. When I was told a few weeks ago that I could begin spending 80% of my time working on the database itself, I was more than thrilled, as for the past 10 months, this was the project I would spend time on for fun, to give myself a break from work.&lt;&#x2F;p&gt;
&lt;p&gt;One of my first tasks was performance, specifically around our async I&#x2F;O implementation (&lt;code&gt;io_uring&lt;&#x2F;code&gt;). Benchmarks and flamegraphs showed that under write-heavy workloads performance would degrade sharply after enough writes. Digging in, this wasn’t just an I&#x2F;O problem, our Write-Ahead Log (WAL) needed some dire attention. The early WAL implementation was sufficient for bootstrapping correctness, but it was now time for a full revamp.&lt;&#x2F;p&gt;
&lt;p&gt;One of several design choices that &lt;code&gt;turso&lt;&#x2F;code&gt; made, is to use the WAL journal mode exclusively. Until MVCC support is finished, this will remain our primary method of transaction isolation, as well as for the usual benefit of journaling, providing durability.&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;code&gt;checkpoint&lt;&#x2F;code&gt; is the process of moving committed frames from the log back into the main database file. There are different &#x27;modes&#x27; of checkpointing, a few of which are: &lt;code&gt;Restart&lt;&#x2F;code&gt; and &lt;code&gt;Truncate&lt;&#x2F;code&gt;, which both restart the log over from the beginning (with &lt;code&gt;truncate&lt;&#x2F;code&gt; then going on to physically truncate the WAL file afterwards), and &lt;code&gt;Passive&lt;&#x2F;code&gt;, which is the default mode that will be triggered periodically by default during the pager&#x27;s cache flush method.&lt;&#x2F;p&gt;
&lt;p&gt;There are a number of locks that are shared between all connections, which must be held either exclusively by a writer or a checkpointer, or by readers to signify that there is an active read transaction going on, and what the maximum frame is for that read transaction.&lt;&#x2F;p&gt;
&lt;p&gt;The checkpoint operation, sort of like a read transaction, also has it&#x27;s own min and maximum frames that it needs to &lt;code&gt;backfill&lt;&#x2F;code&gt; (backfilling is the process of writing pages from the log to the database). All the current readers are evaluated and depending on the checkpoint&#x27;s Mode, either the checkpoint&#x27;s max_frame is decreased, or a Busy error is returned, to prevent moving frames which are not in the reader&#x27;s snapshot to the database file, where the reader might see them before they should.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-simplified-checkpoint-flow&quot;&gt;The (simplified) checkpoint flow&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Trigger:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Either:
a. At the end of a write transaction, during cacheflush process the log will check if the amount of frames in the cache is greater than a specific threshold (typically 1000 frames), and auto-trigger PASSIVE checkpoint.
&lt;br &#x2F;&gt;
b. An explicit &lt;code&gt;PRAGMA wal_checkpoint(mode);&lt;&#x2F;code&gt; is executed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Process outline:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Locking:&lt;&#x2F;strong&gt; Acquire the checkpoint locks needed for the chosen mode (e.g., &lt;code&gt;checkpoint_lock&lt;&#x2F;code&gt; and &lt;code&gt;read-mark 0&lt;&#x2F;code&gt; for all modes, and modes that require “all frames” also hold the exclusive writer lock).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Safe bound:&lt;&#x2F;strong&gt; Compute the checkpoint&#x27;s max_frame by examining active readers, capping it to the lowest pinned frame among them. The previous checkpoint’s max is stored as &lt;code&gt;nBackfills&lt;&#x2F;code&gt;, which denotes the current checkpoint&#x27;s min_frame.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Worklist:&lt;&#x2F;strong&gt; Build the list of &lt;code&gt;(page_id → latest_frame ≤ max_frame)&lt;&#x2F;code&gt; candidates to backfill.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Copy:&lt;&#x2F;strong&gt; For each selected frame, issue a read from the WAL and write the page into the main DB file at its offset.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Finalize:&lt;&#x2F;strong&gt; If &lt;strong&gt;all&lt;&#x2F;strong&gt; possible frames were backfilled, &lt;code&gt;fsync&lt;&#x2F;code&gt; and truncate the DB as needed, and depending on mode, restart&#x2F;truncate the WAL; advance &lt;code&gt;nBackfill&lt;&#x2F;code&gt;. Release locks and return counts.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;So what are the performance issues here?&lt;&#x2F;p&gt;
&lt;p&gt;Copied frames one at a time, with strictly serialized reads and writes.&lt;&#x2F;p&gt;
&lt;p&gt;Issued writes in no particular page order (whatever order they came from the frame cache in).&lt;&#x2F;p&gt;
&lt;p&gt;Never looked at the in-memory page cache, so even already-hot pages were re-read from the WAL every time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;Symptoms:&lt;&#x2F;strong&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Lots&lt;&#x2F;strong&gt; of syscalls, poor locality.&lt;&#x2F;p&gt;
&lt;p&gt;Average checkpoint time was roughly 8-13 ms on a representative test on my machine.&lt;&#x2F;p&gt;
&lt;p&gt;CPU stalled on I&#x2F;O and cache misses, even for warm pages.&lt;&#x2F;p&gt;
&lt;p&gt;Correct, but not ideal.&lt;&#x2F;p&gt;
&lt;p&gt;One of the most exciting features we are introducing in &lt;code&gt;tursodb&lt;&#x2F;code&gt; not found in SQLite is Async I&#x2F;O (via &lt;code&gt;io_uring&lt;&#x2F;code&gt;), This allows us to do things concurrently, so the previous setup of having all writes fully serialized awaiting the reads, is not exactly ideal here.&lt;&#x2F;p&gt;
&lt;p&gt;I had recently introduced using vectored I&#x2F;O for any contiguous pages that are written to the DB file, so we could read in batches of pages, and then submit single &lt;code&gt;pwritev&lt;&#x2F;code&gt; syscalls with a provided array of buffers, for any groups of page ID&#x27;s that were sequential. This helped increase performance, but the serialization of the reads was still a bottleneck.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Old flow:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ acquire proper locks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ compute mxSafeFrame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ build (page_id, latest_frame≤mxSafeFrame) list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ → ReadPage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ReadPage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ Issue `pread` for current page&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ → WaitReadPage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;WaitReadPage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ Check if current page still locked (awaiting I&#x2F;O)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ Locked? if pages =&amp;lt; batch_len -&amp;gt; FlushBatch : return I&#x2F;O&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;FlushBatch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ Collect buffers from current batch of read pages&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ Issue a `pwritev` for each contiguous run.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ Store marker to track completion of run.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ → WaitFlushBatch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;WaitFlushBatch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ If Batch complete:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─── More reads ? ReadPage : Done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ Else? return I&#x2F;O&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ fsync db file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ advance nBackfill and increment checkpoint_seq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ (Restart&#x2F;Truncate modes) if all frames backfilled, reset the log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ release locks, return counts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;New proposed flow&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  Start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ acquire proper locks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ compute mxSafeFrame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ build (page_id, latest_frame≤mxSafeFrame) list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ → Processing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Processing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ drain completed reads into a WriteBatch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ flush WriteBatch when “good enough” (based on run-length heuristics)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ issue more reads until limits are hit&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ loop until nothing is left&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ → Done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Done&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ fsync db file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ advance nBackfill and increment checkpoint_seq&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  ├─ (Restart&#x2F;Truncate modes) if all frames backfilled, reset the log&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  └─ release locks, return counts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;How can we trust that the cached pages are the exact frames we need? SQLite reads each page from the log during checkpoint, so why diverge from this?&lt;&#x2F;p&gt;
&lt;p&gt;We encode an &#x27;epoch&#x27; and store it on the page object in memory, a packed combination of the &lt;code&gt;frame_id&lt;&#x2F;code&gt;, and the &lt;code&gt;checkpoint_seq&lt;&#x2F;code&gt;, which is an integer stored on the WAL header that is incremented at each successful checkpoint. So in addition to ensuring that the page is not dirty, we make sure it matches the exact frame and generation. To be even more secure, when debug assertions are enabled, we still read the page from the log and we assert that it has the same contents of any page we would have accepted from the cache.&lt;&#x2F;p&gt;
&lt;p&gt;This results in excellent percentage of cache hits for write benchmarks or any write heavy loads. It is likely to be less during any read heavy workloads, as we won&#x27;t have all the relevant frames in memory due to being evicted to make room for the read pages, but this still a tremendous win compared to a guaranteed 2 syscalls per-page.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;So Why doesn&#x27;t SQLite do this?&lt;&#x2F;strong&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;SQLite tends to be conservative in terms of performance optimizations, and is more likely to keep things simple. Also, since SQLite allows multi-process connections, there are many instances where the page cache will either be empty, or not shared between connections, making this optimization not nearly as useful.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;strong&gt;New Benchmarks?:&lt;&#x2F;strong&gt;&lt;&#x2F;strong&gt;
(Average time spent checkpointing during write benchmark)&lt;&#x2F;p&gt;
&lt;p&gt;Before: &lt;code&gt;7-12ms&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After: &lt;code&gt;2-5ms&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Learn systems, not langauges</title>
          <pubDate>Sat, 09 Aug 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/learn-systems/</link>
          <guid>https://pthorpe92.dev/learn-systems/</guid>
          <description xml:base="https://pthorpe92.dev/learn-systems/">&lt;p&gt;Due to the nature of my story and the attention that it&#x27;s received, as mentioned in my last &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;turso.tech&#x2F;blog&#x2F;working-on-databases-from-prison&quot;&gt;post&lt;&#x2F;a&gt;, I frequently get emails from developers, college kids, or other people with troubled pasts that are looking for advice on either how to learn or how to get into tech. This blog post will be a compilation of things I have typed out probably a hundred times now, which I hope might help anyone who seeks such advice, and which I can point to that effectively sums up my insight and learnings.&lt;&#x2F;p&gt;
&lt;p&gt;I went from not having written any code in 15+ years, to programming for ~16 hours a day for about three and a half years now. One of the things I am most thankful for, is my past experience programming, while it did not leave me with much remaining skill or experience, it did at least get me in the right direction, and I at least knew &lt;em&gt;what&lt;&#x2F;em&gt; I should be spending my time on.&lt;&#x2F;p&gt;
&lt;p&gt;At the start, I was only able to get the python interpreter and use the bundled &#x27;IDLE&#x27; Tkinter python IDE (on a heavily locked-down Windows 10 laptop with 8GB of RAM btw), and there was no internet except at the Recreation building which we had limited hours in, only on weekdays. So I had to save wikipedia articles and copy + paste code from github and stack overflow into .txt files, because there was definitely no access to git at that time. Eventually started writing C and Go and building my own library of data structures before I got my first job a couple years ago. Everything was so fascinating to me, and I sat and absorbed every piece of tech culture, history and lore that I could find. A lot of things were coming back to me, and perhaps the nostalgia is what had so much of an impact on me, is that it reminded me of a time before I had thrown my life away, and things were much more simple.&lt;&#x2F;p&gt;
&lt;p&gt;Roughly twenty thousand hours of programming later, I now spend my work days hacking on database internals.&lt;&#x2F;p&gt;
&lt;p&gt;The first thing I would like to mention about this, is that there are zero short-cuts, and no substitute for all those hours spent. The best thing you can hope for is that the hours you spend will be as rewarding and fruitful as possible. You could &lt;em&gt;easily&lt;&#x2F;em&gt; spend the same amount of time misguided and unaware of what to learn, and end up squandering a significant portion of it.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#x27;s called Tutorial hell because Tutorials are the devil.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;There are great resources out there, like Harvard&#x27;s CS50 or I&#x27;m sure some of the code academy lessons are great, and &lt;code&gt;https:&#x2F;&#x2F;boot.dev&lt;&#x2F;code&gt; (shout-out to Lane, is a really good guy and although I never took any courses myself, I had recommended my &#x27;protege&#x27; to sign up and use it to study and learn in between our weekly meetings and it really does a great job of teaching a lot of fundamentals in a structured and gamified way) is pretty great.&lt;&#x2F;p&gt;
&lt;p&gt;But the youtube &lt;code&gt;tutorials&lt;&#x2F;code&gt; that claim you can learn X in Y minutes, or they have some project you follow along with, is a complete and utter waste of your time.&lt;&#x2F;p&gt;
&lt;p&gt;My biggest piece of advice can be boiled down to this:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Learn &lt;strong&gt;systems&lt;&#x2F;strong&gt;, not languages or frameworks.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;One thing that confuses most new (and not so new) learners, is mistaking a language or framework itself, with the important aspect of &#x27;building software&#x27;.&lt;&#x2F;p&gt;
&lt;p&gt;This applies especially for the demographic that I seem to hear from most frequently. People who, like myself, came from (usually back-end) Web, who maybe learned some Rust or Zig and now want to look for Rust jobs and are having a hard time. This is not uncommon because these languages have some considerable hype around them and are generally challenging and an exciting thing to learn.&lt;&#x2F;p&gt;
&lt;p&gt;The lesson here, is that &lt;strong&gt;most&lt;&#x2F;strong&gt; of companies hiring for Rust jobs are not looking for &#x27;rust developers&#x27;, they are usually looking for devs with a strong systems background. Usually the language will end up being in C++ or C, but that is almost completely irrelevant here. What they want is someone who deeply understands POSIX&#x2F;OS API&#x27;s, filesystem and networking I&#x2F;O and protocols, memory, atomics and threads, etc, etc.&lt;&#x2F;p&gt;
&lt;p&gt;Learn the languages as a &lt;em&gt;side effect&lt;&#x2F;em&gt; of practicing and studying building software. Learn and experience for yourself what problems Rust solves before you spend time learning it. You cannot truly appreciate the ownership&#x2F;borrowing model unless you have dealt with the frustration of keeping track of which poorly documented C libraries mutate or &lt;code&gt;free&lt;&#x2F;code&gt; resources, or had to scan all your code to try to determine what the &lt;code&gt;lifetime&lt;&#x2F;code&gt; of your own objects are after you have passed their pointers to libraries you wrote a while ago.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s not any different if your goals are just to get into tech in general.. It may be tempting to spend all your time learning NextJS, React and tailwindcss, because those seem to be what companies are looking for. But the truth is that now that LLM&#x27;s are quite good at generating this type of code, none of those things are &lt;strong&gt;actually&lt;&#x2F;strong&gt; valuable to a company by themselves in the long run, if you don&#x27;t deeply understand the architecture of HTTP servers and web technology, how scalable web apps are built and shipped.&lt;&#x2F;p&gt;
&lt;p&gt;If you are looking to get into web, make sure you are gaining a fundamental understanding of the HTTP protocol, basic networking, containers and the docker&#x2F;OCI ecosystem, databases, message queue&#x27;s, learn SQL even if you always use an ORM. Learn (and experience for yourself) what problems React solves by building a reactive UI with just vanilla JS and the DOM API.&lt;&#x2F;p&gt;
&lt;p&gt;Prefer Go to Django, Laravel or NextJS, use &lt;code&gt;net&#x2F;http&lt;&#x2F;code&gt; to build &lt;em&gt;your own&lt;&#x2F;em&gt; web framework and understand how they work. Abstractions are great and come in very handy when you are just trying to ship things and you don&#x27;t want to deal with building a session table and your own middleware to be able to call &lt;code&gt;request.UserID()&lt;&#x2F;code&gt; or &lt;code&gt;request.IsAdmin()&#x2F;IsAuthenticated()&lt;&#x2F;code&gt; in your handlers, but if you don&#x27;t understand &lt;em&gt;how&lt;&#x2F;em&gt; that framework knows who sent that request, and how they are logged in, then getting good at that framework is not really providing you any real long term value, I would argue that you are doing yourself a disservice by using it.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Ditch the file-explorer. Embrace the CLI.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I&#x27;m not saying that everyone needs to be a vim user, but I &lt;strong&gt;highly&lt;&#x2F;strong&gt; recommend it. You &lt;strong&gt;will&lt;&#x2F;strong&gt; thank me in a couple months if you spend the time to learn at least the bindings. Working out of the CLI makes you a better programmer, I don&#x27;t care what anyone says. You may know some ultra cracked dev who clicks around file explorers and some light-mode IDE and knows or uses zero keybindings for anything... but that is the exception, not the rule. Computers take some input -&amp;gt; process it -&amp;gt; produce some output, and CLI tools help you think in this paradigm. I&#x27;m not saying you are wrong for using a GUI for everything, I&#x27;m saying learning to be good at the CLI is a major career hack if you want to be a programmer.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Install and configure a minimal installation of Arch Linux.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;You want to be deeply familiar with your system, write and edit your config files yourself. If you need a cronjob setup or to write a SystemD service file, it should be second nature.&lt;&#x2F;p&gt;
&lt;p&gt;Write shell scripts to automate even normal things. I have hand written shell scripts, some of which are years old, that do stupid things like change my desktop wallpaper, update discord, prune my docker cache, build and deploy my blog, removed unused files from my ~&#x2F;Downloads directory, initialize key re-mapping on startup, I have a slack bot that listens to a channel and plays the sound of police sirens when we have an incident that needs acknowledgement. These are all small but valuable things that create a better understanding of how all the software you interact with operates.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Build. Build. Build.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;There is no substitute for building software if you want to get good at building software.&lt;&#x2F;p&gt;
&lt;p&gt;The following is a list of projects that I recommend. These are geared towards anyone interested in systems, but imho there should not be a distinction. Learn computer science if you want to be a good programmer.&lt;&#x2F;p&gt;
&lt;p&gt;NOTE: Most of these are not easy or beginner projects, these are for after you have learned to program and you are comfortably writing web back-ends.&lt;&#x2F;p&gt;
&lt;p&gt;All of these are really preferable to be written in either C, C++, Rust, or Zig. But C is preferred if you haven&#x27;t written any of these languages.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;hey, didn&amp;#39;t he just say &amp;#39;learn systems, not languages.. &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;then proceeds to tell you specifically which language to use?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;em&gt;touche&lt;&#x2F;em&gt;.. HN commentor... touche&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Data structures:&lt;&#x2F;p&gt;
&lt;p&gt;Implement your own library for common things like a string type, dynamic array and hashmap, all from scratch. It&#x27;s preferred that this is used in future projects.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;coreutils:&lt;&#x2F;p&gt;
&lt;p&gt;cat&#x2F;less, ls, mv&#x2F;cp, and find&#x2F;grep. For grep, you don&#x27;t have to implement a whole regex engine, you can just do &lt;code&gt;glob&lt;&#x2F;code&gt; or have fun designing a more simple engine with custom rules. Otherwise you can make them as simple or as feature complete as you want&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;shell:&lt;&#x2F;p&gt;
&lt;p&gt;Lots of fun, and a good warm up for an interpreter or compiler. Learn about environments, subprocesses, signals, traps, inheriting env vars, string interpolation and variable expansion. Learn why &lt;code&gt;cd&lt;&#x2F;code&gt; is the only shell command that works when you yeet your &lt;code&gt;$PATH&lt;&#x2F;code&gt;, and how &lt;code&gt;fork&lt;&#x2F;code&gt; and &lt;code&gt;exec&lt;&#x2F;code&gt; work, what even is POSIX and why do people care when they complain that your favorite shell isn&#x27;t compliant? The general point here is to be as familiar as possible with libc and POSIX&#x2F;linux api&#x27;s and system calls.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;http1 server:&lt;&#x2F;p&gt;
&lt;p&gt;Use raw linux sockets and bind&#x2F;accept&#x2F;send&#x2F;recv syscalls, the HTTP parsing doesn&#x27;t have to be completely up to spec of course, but it should handle basic requests. You can handle each connection on it&#x27;s own thread, but it is really preferable to learn &lt;code&gt;epoll&lt;&#x2F;code&gt; and your &lt;code&gt;accept&lt;&#x2F;code&gt; should be non-blocking. Bonus points for connection pooling with an LRU cache.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Interpreter&#x2F;Compiler:&lt;&#x2F;p&gt;
&lt;p&gt;This is a lot of fun, can be any language. &lt;code&gt;writing an interpreter in Go&lt;&#x2F;code&gt; by Thorsten Ball is a good book (I haven&#x27;t actually read it but I have heard really good things and I have skimmed some of it, plus the author is a gigachad 11x programmer). Demystify what is happening when you write and run code, you don&#x27;t have to write an optimizing x86-64 back-end (I sure as hell didn&#x27;t) to get a &lt;em&gt;ton&lt;&#x2F;em&gt; of value from this project. If this seems very advanced, maybe start by writing &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jamiebuilds&#x2F;the-super-tiny-compiler&quot;&gt;the super tiny compiler&lt;&#x2F;a&gt; in your language of choice, or at the very least learn to write recursive descent parsers. Designing your own bytecode and VM is particularly fun, and its super valuable to learn about labels and jump tables and how loops and branches work at the assembly or bytecode level.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Memory allocator (C):&lt;&#x2F;p&gt;
&lt;p&gt;Write a library that mmap&#x27;s a large chunk of memory on initialization and learn about how to manage the book-keeping and fragmentation, and what trade-offs are made by different kinds of allocators. Ginger Bill has a fantastic series on allocators found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gingerbill.org&#x2F;series&#x2F;memory-allocation-strategies&#x2F;&quot;&gt;here&lt;&#x2F;a&gt; that I highly recommend.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Emulator:&lt;&#x2F;p&gt;
&lt;p&gt;The Chip8 is a great first emulator project. The 8080, and 6502 are much more advanced, but all are very valuable projects to understand particularly CPU internals, memory addressing and probably bit manipulation more than anything.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some others are a Cache, a basic TUI Text Editor (bummer I have never got around to this one), Stackful coroutine based Async I&#x2F;O library (this was a lot of fun in Rust, basically implementing goroutines, backed by io_uring).&lt;&#x2F;p&gt;
&lt;p&gt;This post is getting long and out of hand, maybe I&#x27;ll refactor this out into a separate page of just the project recommendations and gather up some more useful links. But thanks for reading and I hope this is able to help someone.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>whois pthorpe92.dev</title>
          <pubDate>Thu, 19 Jun 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/pages/about/</link>
          <guid>https://pthorpe92.dev/pages/about/</guid>
          <description xml:base="https://pthorpe92.dev/pages/about/">&lt;h1 id=&quot;preston-thorpe&quot;&gt;Preston Thorpe&lt;&#x2F;h1&gt;
&lt;div style=&quot;display:flex; gap:1rem; justify-content:left;&quot;&gt;
  &lt;figure style=&quot;text-align:center;&quot;&gt;
    &lt;img src=&quot;&#x2F;profile.png&quot; style=&quot;width:200px;&quot;&gt;
  &lt;&#x2F;figure&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;senior engineer @ &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;turso.tech&quot;&gt;Turso&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;building the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tursodatabase&#x2F;limbo&quot;&gt;modern evolution of sqlite&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;formerly:&lt;&#x2F;p&gt;
&lt;p&gt;principal engineer @ &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unlockedlabs.org&quot;&gt;Unlocked Labs&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;open-source&quot;&gt;open source:&lt;&#x2F;h3&gt;
&lt;p&gt;maintainer @ &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;eza-community&#x2F;eza&quot;&gt;eza&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;maintainer @ &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;unlockedlabs&#x2F;unlockedv2&quot;&gt;UnlockEdv2&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;=====================================================================&lt;&#x2F;p&gt;
&lt;p&gt;Currently incarcerated at MVCF in Charleston, ME. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pthorpe92.dev&#x2F;intro&#x2F;my-story&quot;&gt;story&lt;&#x2F;a&gt;)
&lt;br &#x2F;&gt;
cli, linux, and rust nerd.
&lt;br &#x2F;&gt;
open source enthusiast
&lt;br &#x2F;&gt;
systems&#x2F;databases&#x2F;cloud&#x2F;devops&lt;&#x2F;p&gt;
&lt;p&gt;I love Rust, Go, CLI&#x2F;TUI&#x2F;all things &lt;code&gt;tty&lt;&#x2F;code&gt;, databases, cloud&#x2F;infra, building developer tools,
systems programming, the Open source community, and I enjoy teaching. I&#x27;m a long time linux user
(I&#x27;ve had a ubuntu tattoo since &#x27;09), some of my favorite tools are DWM&#x2F;awesomewm, Neovim, Tmux, Ghostty and Alacritty.&lt;&#x2F;p&gt;
&lt;p&gt;I am an advocate for FOSS, privacy, security, criminal justice&#x2F;prison reform,
but most of all for hard work and discipline. I enjoy working on anything challenging, and I consider myself extremely fortunate that
I have a career that doubles as a hobby.&lt;&#x2F;p&gt;
&lt;p&gt;I believe that I&#x27;m a living example of why education is the solution to mass incarceration. Access to
education and technology while incarcerated changed my life completely and I want to be a part of helping give
more people the opportunity I had, to study and devote time to building the skills necessary to have
a meaningful life and career when they re-enter society.&lt;&#x2F;p&gt;
&lt;p&gt;These are some developers I look up to, or projects that have inspired me that I feel are worth sharing: (all unrelated to me)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;awesomekling&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;awesomekling&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;apavlo&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;apavlo&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;dtolnay&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andrewrk&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;andrewrk&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;artempyanykh&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;artempyanykh&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tjdevries&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;tjdevries&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fasterthanlime&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;fasterthanlime&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tokio&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;tokio&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;LadyBirdBrowser&#x2F;ladybird&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;LadyBirdBrowser&#x2F;ladybird&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;ziglang&#x2F;zig&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ratatui-org&#x2F;ratatui&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;ratatui-org&#x2F;ratatui&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;uutils&#x2F;coreutils&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;uutils&#x2F;coreutils&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mrnugget&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;mrnugget&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;orhun&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;orhun&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;penberg&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;penberg&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;sunfishcode&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mitchellh&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;mitchellh&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Working on databases from prison, How I got here, part 2.</title>
          <pubDate>Mon, 16 Jun 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/how-i-got-here-part-2/</link>
          <guid>https://pthorpe92.dev/how-i-got-here-part-2/</guid>
          <description xml:base="https://pthorpe92.dev/how-i-got-here-part-2/">&lt;h2 id=&quot;how-i-got-here-pt-2&quot;&gt;How I got here pt. 2&lt;&#x2F;h2&gt;
&lt;p&gt;Posted on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;turso.tech&#x2F;blog&#x2F;working-on-databases-from-prison&quot;&gt;turso&#x27;s blog&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Calling Rust from cursed Go</title>
          <pubDate>Wed, 26 Feb 2025 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/cursed-go/</link>
          <guid>https://pthorpe92.dev/cursed-go/</guid>
          <description xml:base="https://pthorpe92.dev/cursed-go/">&lt;h1 id=&quot;the-general-state-of-ffi-in-go&quot;&gt;The general state of FFI in Go&lt;&#x2F;h1&gt;
&lt;p&gt;can be expressed well with a story about when I had tried to get &lt;code&gt;mattn&#x2F;go-sqlite3&lt;&#x2F;code&gt; drivers
to work on a Windows machine a couple years ago around version &lt;code&gt;1.17&lt;&#x2F;code&gt;, and CGO would not build properly because my $GOPATH
or $CC was in &lt;code&gt;C:\Program Files\&lt;&#x2F;code&gt; and it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;golang&#x2F;go&#x2F;issues&#x2F;41400&quot;&gt;split the path on the whitespace&lt;&#x2F;a&gt;.
Although I personally find the use of whitespace in system paths especially (and just windows in general) to be a tragedy, I was shocked that this was a real problem.&lt;&#x2F;p&gt;
&lt;p&gt;Other than dealing with some random cross platform issues that teammates would have before we switched
to using the &lt;code&gt;modernc&#x2F;sqlite3&lt;&#x2F;code&gt; driver, I didn&#x27;t have any experience &lt;em&gt;writing&lt;&#x2F;em&gt; CGO. I&#x27;ll admit that
I was maybe a bit ignorant to the details of exactly &lt;em&gt;why&lt;&#x2F;em&gt; it sucked, but the bad user experiences and
many anecdotes I&#x27;d heard were enough for me to look elsewhere for solutions when it came time to needing to
call foreign symbols in dynamically linked libraries from a Go program.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;so-why-does-cgo-suck&quot;&gt;So why does CGO suck?&lt;&#x2F;h3&gt;
&lt;p&gt;==============================&lt;&#x2F;p&gt;
&lt;p&gt;There have been many posts and videos that document this far better than I could, probably the most popular being &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dave.cheney.net&#x2F;2016&#x2F;01&#x2F;18&#x2F;cgo-is-not-go&quot;&gt;this&lt;&#x2F;a&gt; post from Dave Cheney. A quick summary would be:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;For performance, Go using CGO is going to be closer to Python than Go. (which doesn&#x27;t mean it&#x27;s not still significantly faster than python)&lt;&#x2F;li&gt;
&lt;li&gt;CGO is slow and often still painful to build cross platform.&lt;&#x2F;li&gt;
&lt;li&gt;Go is no longer able to be built into a single static binary.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This being said, if I can find a solution that solves even 1 of these three things, I would consider that a W.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;the-program-in-question&quot;&gt;The program in question:&lt;&#x2F;h3&gt;
&lt;p&gt;==============================&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tursodatabase&#x2F;limbo&quot;&gt;Limbo&lt;&#x2F;a&gt; is an open source, modern Rust reimplementation of sqlite&#x2F;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tursodatabase&#x2F;libsql&quot;&gt;libsql&lt;&#x2F;a&gt; that I have become heavily involved in during the last few months in my spare time.&lt;&#x2F;p&gt;
&lt;p&gt;One of my primary contributions has been developing the extension library, where I am focused on providing (by way of many procedural macros)
the most intuitive and simple API possible for users who wish to extend limbo&#x27;s functionality with things like functions,
virtual tables and virtual filesystems in safe Rust (and eventually other languages), without users having to write any of the ugly and confusing
unsafe&#x2F;FFI code that is currently required to extend sqlite3 in any way.&lt;&#x2F;p&gt;
&lt;p&gt;Since &lt;code&gt;limbo&lt;&#x2F;code&gt; is written in Rust and the extensions need to be able to be loaded dynamically at runtime, even though both extension library and core
are both in Rust, unfortunately this means that Rust must fall back to adhering to &lt;code&gt;C&lt;&#x2F;code&gt; ABI to call itself, and most of the goodies (traits,
smart pointers, etc) and memory safety that Rust gives us by default are all out the window.&lt;&#x2F;p&gt;
&lt;p&gt;However with Rust, aside from that unfortunate situation, once you get used to it, &lt;code&gt;FFI&lt;&#x2F;code&gt; in general is a rather pleasant experience that I can
equate to writing a better C with lots of features, or I can imagine something similar to Zig (shot in the dark, I haven&#x27;t yet written zig).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;what-this-has-to-do-with-go&quot;&gt;What this has to do with Go:&lt;&#x2F;h3&gt;
&lt;p&gt;==============================&lt;&#x2F;p&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tursodatabase&#x2F;limbo&#x2F;issues&#x2F;506&quot;&gt;github issue&lt;&#x2F;a&gt; for limbo was created, asking if a Go driver would be available. The most common theme
between almost all the relevant comments was: &lt;code&gt;avoid CGO&lt;&#x2F;code&gt; (including my own, due to my previous interactions with it).&lt;&#x2F;p&gt;
&lt;p&gt;As a Go developer by profession, after a couple weeks of no activity on the issue, I decided that I would take on that task as well.&lt;&#x2F;p&gt;
&lt;p&gt;Besides a jank, half finished, speed-run &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PThorpe92&#x2F;ayc&quot;&gt;programming language&lt;&#x2F;a&gt;, I have almost exclusively used Go to write backends and web services,
which basically everyone agrees is where it really shines. Most of the systems or general programming outside of web that I have done, has all been in
Rust or C&#x2F;C++ (mostly Rust). I say that to highlight that my knowledge and experience with Go and the ecosystem outside of web was&#x2F;is minimal, so I was more
or less starting from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;All I knew at first was that I didn&#x27;t want to use CGO, and I had heard of other packages that were supposedly &#x27;Pure Go&#x27; implementations.
So I naively figured there must be a way to just ignore whatever API the Go team wants you to use, and perhaps there is some &#x27;unsafe&#x27; platform
specific os package that lets you &lt;code&gt;dlopen&lt;&#x2F;code&gt; that people just avoid for one reason or another.&lt;&#x2F;p&gt;
&lt;p&gt;I started to look at how other drivers managed this, and realized that all of Go&#x27;s current options for sqlite3 drivers, fall into one of the
following categories:&lt;&#x2F;p&gt;
&lt;p&gt;(note: although there are a few more drivers out there that I have not named, they would be still included in one of the below categories).&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;CGO:&lt;&#x2F;strong&gt; &lt;code&gt;github.com&#x2F;mattn&#x2F;go-sqlite3&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;The defacto-standard and the first search result on Google for &#x27;go sqlite driver&#x27;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;Code-gen:&lt;&#x2F;strong&gt; &lt;code&gt;modernc.org&#x2F;sqlite&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;An extremely impressive project that generates Go code for the entire sqlite codebase, as well as some supporting libc code,
for many different platforms.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;WASM:&lt;&#x2F;strong&gt; &lt;code&gt;github.com&#x2F;ncruces&#x2F;go-sqlite3&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;Uses a wasm build of sqlite3 and packages the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wazero.io&#x2F;&quot;&gt;wazero&lt;&#x2F;a&gt; runtime, as well as a Go vfs implementation wrapping
sqlite3&#x27;s OS interface. Has some minor caveats, but is production ready and well implemented.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;Pipes:&lt;&#x2F;strong&gt; &lt;code&gt;github.com&#x2F;cvilsmeier&#x2F;sqinn-go&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;reads requests from stdin, forwards the request to SQLite, and writes a response to stdout.&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;why-can-t-i-just-dlopen&quot;&gt;&lt;em&gt;Why can&#x27;t I just &lt;code&gt;dlopen()&lt;&#x2F;code&gt;?&lt;&#x2F;em&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When I was unable to find anything that remotely resembles &lt;code&gt;dlopen&lt;&#x2F;code&gt; in the Go standard library (except for &lt;code&gt;windows.LoadLibrary()&lt;&#x2F;code&gt; surprisingly,
but more on that in my next post), I recalled a conversation I had with my boss&#x2F;CTO at work.&lt;&#x2F;p&gt;
&lt;p&gt;She has been writing Go since the first open source release, and that is one of the things we originally bonded over,
was the desire to move the company from PHP to Go. I remembered her telling me about a Game engine written in Go that wrote it&#x27;s own CGO
replacement because of how annoyed they were with CGO itself. I was now curious and decided to check it out.&lt;&#x2F;p&gt;
&lt;p&gt;Enter: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ebitengine&#x2F;purego&quot;&gt;purego&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;A library that allows you to &lt;code&gt;dlopen()&lt;&#x2F;code&gt;&#x2F;&lt;code&gt;dlsym()&lt;&#x2F;code&gt; in Go without CGO. After looking at the API, I quickly realized that this is exactly
what I was looking for.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;But how did they do it?&lt;&#x2F;em&gt;
&lt;img src=&quot;&#x2F;pepethink.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;syscall&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;a1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; syscall&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;a2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; syscall_syscall15X&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;cfn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;5&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;6&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;7&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;9&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;10&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;11&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;12&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;13&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;],&lt;&#x2F;span&gt;&lt;span&gt; sysargs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;14&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;syscall&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;f1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; syscall&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;a2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; &#x2F;&#x2F; on amd64 a2 stores the float return. On 32bit platforms floats aren&amp;#39;t support&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;rawdogging syscalls, apparently...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;calling-rust-from-cursed-go&quot;&gt;Calling Rust from cursed Go&lt;&#x2F;h2&gt;
&lt;p&gt;==============================&lt;&#x2F;p&gt;
&lt;p&gt;Purego makes registering foreign symbols very simple. When the driver is registered, I &lt;code&gt;dlopen()&lt;&#x2F;code&gt; the library and&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; Adapted for brevity&#x2F;demonstration&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;var&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	libOnce&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;           sync&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Once&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	limboLib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;          uintptr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	dbOpen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;            func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; uintptr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	dbClose&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;           func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;uintptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; uintptr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	connPrepare&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;       func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;uintptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; uintptr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; ... all the function pointers at global scope&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; Register all the symbols on library load&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; ensureLibLoaded&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	libOnce&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Do&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         limboLib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; purego&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Dlopen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;libPath&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; purego&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;RTLD_NOW&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;purego&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;RTLD_GLOBAL&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span&gt; err&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;            return&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;                     &#x2F;&#x2F; functionPointer, uintptr, symbol name string&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		purego&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;RegisterLibFunc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;dbOpen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; limboLib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; FfiDbOpen&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		purego&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;RegisterLibFunc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;dbClose&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; limboLib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; FfiDbClose&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		purego&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;RegisterLibFunc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;connPrepare&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; limboLib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; FfiDbPrepare&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		purego&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;RegisterLibFunc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;connGetError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; limboLib&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; FfiDbGetError&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;        &#x2F;&#x2F; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After playing around with it a bit, and deciphering what my types needed to look like to properly pass values back and forth
from Rust, I ended up with something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; valueType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; int32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;	intVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;  valueType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;	textVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; valueType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;	blobVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; valueType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;	realVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; valueType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;	nullVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; valueType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; struct to send values over FFI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; limboValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;  valueType&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	_&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;     [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; &#x2F;&#x2F; padding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Blob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; uintptr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  int64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I had to use a byte slice instead of a &lt;code&gt;uintptr&lt;&#x2F;code&gt; if I wanted to represent a union and possibly interpret those bytes as an
int64 or float64, as well as a pointer to a TextValue or BlobValue struct that stores the bytes + length&lt;&#x2F;p&gt;
&lt;p&gt;With the accompanying Rust type:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;repr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub enum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; ValueType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;    Integer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;    Text&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;    Blob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;    Real&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;    Null&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;repr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub struct&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; LimboValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    value_type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; ValueType&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; ValueUnion&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;repr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;union&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; ValueUnion&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    int_val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; i64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    real_val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; f64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    text_ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;: *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; c_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    blob_ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;: *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span&gt; c_void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is how, for example, I convert the slice of &lt;code&gt;driver.Args&lt;&#x2F;code&gt; that in order to implement &lt;code&gt;statement.Query&lt;&#x2F;code&gt;
from &lt;code&gt;database&#x2F;sql&#x2F;driver&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; convert a Go slice of driver.Value to a slice of limboValue that can be sent over FFI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; for Blob types, we have to pin them so they are not garbage collected before they can be copied&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; into a buffer on the Rust side, so we return a function to unpin them that can be deferred after this call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; buildArgs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;driver&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) ([]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;limboValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(),&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; error&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	pinner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; new&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;runtime&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Pinner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt;                 &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;    &#x2F;&#x2F; I was unaware that runtime.Pinner was a thing, prior to this&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	argSlice&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; make&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;([]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;limboValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;	for&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; range&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; limboValue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		switch&lt;&#x2F;span&gt;&lt;span&gt; val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; nullVal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		case int64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; intVal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; = *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)(&lt;&#x2F;span&gt;&lt;span&gt;unsafe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pointer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		case float64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; realVal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; = *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;8&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)(&lt;&#x2F;span&gt;&lt;span&gt;unsafe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pointer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		case string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; textVal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			cstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; CString&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			pinner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;cstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;			*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;uintptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)(&lt;&#x2F;span&gt;&lt;span&gt;unsafe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pointer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; uintptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;unsafe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pointer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;cstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		case&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; blobVal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			blob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; makeBlob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			pinner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;blob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;			*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;uintptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)(&lt;&#x2F;span&gt;&lt;span&gt;unsafe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pointer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;limboVal&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; uintptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;unsafe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pointer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;blob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		default&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;			return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; pinner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Unpin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; fmt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Errorf&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;unsupported type: %T&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		argSlice&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; limboVal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span&gt; argSlice&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; pinner&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;Unpin&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; convert a byte slice to a Blob type that can be sent over FFI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; makeBlob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Blob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt; nil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Blob&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		Data&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; uintptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;unsafe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pointer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;])),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		Len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  int64&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Looking at purego&#x27;s source code gave me some inspiration and helped me get the general idea of how to manipulate
and work with pointers and types received over FFI. For instance, this is the function they use to convert a Go
string to a C String:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;Credit (Apache2 License) to:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;      https:&#x2F;&#x2F;github.com&#x2F;ebitengine&#x2F;purego&#x2F;blob&#x2F;main&#x2F;internal&#x2F;strings&#x2F;strings.go&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; CString&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; hasSuffix&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt;\x00&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)(&lt;&#x2F;span&gt;&lt;span&gt;unsafe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Pointer&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)))[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; make&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;([]&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;byte&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;	copy&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And I was able to adapt everything else around these concepts. There were a few things that I wasn&#x27;t super pleased with that I still
have to figure out. For instance, sending back an array of strings from Rust was such a pain in the ass that &lt;code&gt;rows.Columns()&lt;&#x2F;code&gt; method
calls this function:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;no_mangle&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;pub extern&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;C&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; rows_get_columns&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;rows_ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;: *&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt; c_void&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; rows_ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;is_null&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; rows&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; LimboRows&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;from_ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;rows_ptr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rows&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;stmt&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;num_columns&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; as i32&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;to get the number of result columns for the prepared statement, then calls &lt;code&gt;rows_get_column_name&lt;&#x2F;code&gt; with the index of the column
name to return.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;it-s-all-pretty-cursed-huh&quot;&gt;It&#x27;s all pretty cursed huh?&lt;&#x2F;h3&gt;
&lt;p&gt;================================&lt;&#x2F;p&gt;
&lt;p&gt;But it works, and so far there is a decent start to bindings that don&#x27;t fit into any of the above
categories with any of the existing sqlite drivers :)&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;ll follow this post up soon with another explaining some of the caveats, the workarounds for them, whether or not we actually
solved any of the issues that we described with CGO, and maybe run some benchmarks.&lt;&#x2F;p&gt;
&lt;p&gt;But for now, thanks for reading.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;PThorpe92&quot;&gt;PThorpe92&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Magic isn&#x27;t real</title>
          <pubDate>Thu, 03 Oct 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/magic/</link>
          <guid>https://pthorpe92.dev/magic/</guid>
          <description xml:base="https://pthorpe92.dev/magic/">&lt;p&gt;&lt;code&gt;Any sufficiently advanced technology is indistinguishable from magic&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Arthur C. Clarke&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This quote applies just as much to developers as it does non-tech people, sometimes more. I remember towards the beginning of
my programming journey (both the first time I learned 18+ years ago, and again ~15 years later), the root cause of the feeling
responsible for what they call &lt;code&gt;tutorial hell&lt;&#x2F;code&gt; (I personally loathe tutorials, and always chose to instead try to build
things myself, and I attribute a great deal of the relative success I have achieved to this).&lt;&#x2F;p&gt;
&lt;p&gt;The situation:&lt;&#x2F;p&gt;
&lt;p&gt;You feel like you understand perfectly how to properly swing a hammer, lay brick, frame drywall, and you learned the right way to measure
and cut beams with a saw, yet you still look at buildings and architecture and stand completely baffled that those tools you have learned
were the same ones used to build these great structures. With no idea where to start, you stare at your tools, supplies and materials
wondering if they must have some kind of special equipment or secret freemason knowledge that you don&#x27;t have access to. You don&#x27;t
know how someone ended up with that result, using the same tools you see in front of you, and you definitely cannot imagine cutting
the first board or laying the first brick.&lt;&#x2F;p&gt;
&lt;p&gt;Many know that this is the exact feeling of learning how to program, and fully grasping the concepts of loops, variables, data structures,
trees, stacks, linked-lists, arrays, control flow, etc, etc, etc... then looking at a compiler, a video game, an operating system,
web browser and thinking &lt;code&gt;yeah right...&lt;&#x2F;code&gt;. Those devs must all have started programming C and x86 assembly while they were in diapers, and
all attended Stanford where they were taught secret knowledge passed down from Ken Thompson, by Brian Kernaghan himself.&lt;&#x2F;p&gt;
&lt;p&gt;Assuming you don&#x27;t take the strict path of the JS frameworker vercel user: eventually after enough time, you start to recognize patterns.
You &#x27;go to definition&#x27; on enough methods from libraries you use to see how they are implemented and you build enough side projects and
watch enough &#x27;tsoding daily&#x27;, &#x27;sphaerophoria&#x27;, and &#x27;awesomekling&#x27; to begin to demystify at least how things like web&#x2F;network protocols,
or image&#x2F;video encodings, syscalls&#x2F;file IO operations work at some level. You no longer would feel completely lost if you had to write
a shell or a &lt;code&gt;lisp&lt;&#x2F;code&gt; interpreter: you would at the very least know that to begin, you would probably have to read the source file into memory and break it up into tokens before trying to parse it to build the syntax tree needed so you can traverse and analyze it before stepping through it to execute the code. Previously, what now feels so obvious to you, would have seemed some kind of sorcery reserved only for the
aforementioned programming elite.&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m sure I&#x27;m not alone, in that each time you pull the curtain off a piece of &#x27;&lt;em&gt;magic&lt;&#x2F;em&gt;&#x27;, you have the same thought:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Oooooh yeah. I mean, well duh.. how else would you do that? I can&#x27;t believe I couldn&#x27;t see it&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;As time goes on, there are less and less things I run into where I cannot mentally parse at least from a very broad and high level, what an
implementation might look like. Now I &lt;em&gt;definitely&lt;&#x2F;em&gt; don&#x27;t claim to know how kernel internals, 3d rendering, or GPU drivers work, but what I
mean is most things have lost the shadowy mystique, and feel more like something I can get excited to learn about, rather than a scary
forbidden knowledge I will never be allowed to possess. Although for those things, that may as well be the case ;)&lt;&#x2F;p&gt;
&lt;p&gt;The other day, after a long day&#x27;s work managing synchronizing different environments&#x2F;k8s clusters, I decided to browse HN as I normally do
at that time. I ran into a post referencing &lt;code&gt;comptime&lt;&#x2F;code&gt; for Go, that linked to a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;pinjg&#x2F;prep&quot;&gt;github repo&lt;&#x2F;a&gt;. It immediately caught
my attention, as although I have not written Zig myself, Andrew Kelly is one of my programming idols and I definitely follow zig&#x27;s development.
Comptime is one of Zig&#x27;s most envied language features, and although it is achievable via metaprogramming or &lt;code&gt;constexpr&lt;&#x2F;code&gt; in other languages,
zig&#x27;s straightforward procedural approach&#x2F;API makes it particularly unique and admired.&lt;&#x2F;p&gt;
&lt;p&gt;This was when I came upon that familiar feeling:&lt;&#x2F;p&gt;
&lt;div style=&quot;text-align:center&quot;&gt;
&lt;img style=&quot;width:50%&quot; src=&quot;&#x2F;how.png&quot; alt=&quot;How tf&quot;&#x2F;&gt;
  &lt;&#x2F;div&gt;
&lt;br&gt;
&lt;div style=&quot;text-align:center&quot;&gt;
&lt;img src=&quot;&#x2F;confused.png&quot; alt=&quot;Confused..&quot;&#x2F;&gt;
  &lt;&#x2F;div&gt;
&lt;br&gt;
^^^^^^
Me if you had told me I had to implement comptime in go without touching the compiler
&lt;p&gt;So I decided that I had to know how this was done, and I had a few hours to spare so I decided I would maybe try to contribute, or at least
add some kind of feature of any level of value, just to force myself to understand what was going on here.&lt;&#x2F;p&gt;
&lt;p&gt;Then after a brief peruse through the code...&lt;&#x2F;p&gt;
&lt;p&gt;Turns out, you can use the source file information you get through this flag you can pass at build time in Go called &lt;code&gt;-toolexec&lt;&#x2F;code&gt;
which allows you to invoke toolchain programs, in this case the &lt;code&gt;prep&lt;&#x2F;code&gt; binary, which is called with the absolute path of the program
and by using a combination of another one of the author&#x27;s packages, &lt;code&gt;goinject&lt;&#x2F;code&gt;, and the &lt;code&gt;yaegi: (yet another elegant Go interpreter)&lt;&#x2F;code&gt;
library: you can get the AST, file decorator and import restorer, by implementing &lt;code&gt;Modifier&lt;&#x2F;code&gt;, which then allows you to collect the variables
from the relevant function in the tree, output them each to a temporary file, on which you run the interpreter, giving you the
computed results of foo in &lt;code&gt;prep.Comptime(foo())&lt;&#x2F;code&gt;, which you then use to replace the values in the DST by the &lt;code&gt;Modify&lt;&#x2F;code&gt; pass.
viola, you have achieved compile time computations.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, well yeah. That makes perfect sense. I mean how else did I think it was gonna work?&lt;&#x2F;p&gt;
&lt;p&gt;After a couple hours, I had added variable scoping, and global const declarations which I concluded was actually
not a useful feature at all, because each function is evaluated on it&#x27;s own, leaving essentially a 0% chance of
actual naming&#x2F;scope conflicts. But the point is, I didn&#x27;t discover that until I had finished writing it with
some tests, and although the &#x27;feature&#x27; is useless, the whole process was a very valuable learning experience and
all around good use of my time.&lt;&#x2F;p&gt;
&lt;p&gt;This is just a reminder to everyone at different levels of their developer journey, that the &quot;magic&quot; is not real and the overwhelming
majority of the time, you are simply lacking the necessary context and it will likely make perfect sense to you as soon as you have it.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s &lt;em&gt;always&lt;&#x2F;em&gt; worth your time to learn parts of the stack that you might not work in daily. As you build your fundamental understanding,
it demystifies other pieces of the puzzle that you would never would have put together otherwise. Even if it doesn&#x27;t feel
important now, I guarantee the knowledge pays off at some point in the future.&lt;&#x2F;p&gt;
&lt;p&gt;Keep learning every day, strive for deeper understanding, and spend time building or hacking on even things that are considered
&#x27;solved problems&#x27;. Even if you are only paid to write React, it is very much of value to you and your career to understand how
the internals work, or how your one-click &#x27;serverless&#x27; auto-scaling deployments work...&lt;&#x2F;p&gt;
&lt;p&gt;(hint: servers)&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>PHP&#x2F;Laravel: Why we rewrote our app in Go</title>
          <pubDate>Sun, 14 Jul 2024 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/from-laravel-to-go/</link>
          <guid>https://pthorpe92.dev/from-laravel-to-go/</guid>
          <description xml:base="https://pthorpe92.dev/from-laravel-to-go/">&lt;h3 id=&quot;modern-php-does-it-really-suck&quot;&gt;(Modern) PHP: Does it really suck?&lt;&#x2F;h3&gt;
&lt;p&gt;Like many, many developers out there over the age of 30, I basically started my programming journey with PHP (and perl).
Circa ~&#x27;05, PHP was &lt;em&gt;the&lt;&#x2F;em&gt; go-to language for the web, and Adobe Dreamweaver supported it out of the box! Most HTML was
hand-written, most connections were absent TLS, and lots of form data was still being stuffed raw-dog right into SQL queries.&lt;&#x2F;p&gt;
&lt;p&gt;This, I estimate, is what is responsible for 69.420% of the hate PHP gets today. (The rest comes from JS andys who have never
seen or written a line of it, who likely just want to deflect some of the flak)&lt;&#x2F;p&gt;
&lt;p&gt;When I was hired at my current job, due to my situation of being currently incarcerated &lt;a href=&quot;&#x2F;intro&#x2F;my-story&quot;&gt;see my other post&lt;&#x2F;a&gt;,
I was happy to find any dev work, and in absolutely no position to be picky about the tech stack. I learned that we would be using &lt;code&gt;Laravel&lt;&#x2F;code&gt;, and PHP 8.2 for the
backend, and although I had less than enthusiastic feelings about PHP itself, I had heard good things about Laravel and dove in head-first.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;Background info:&lt;&#x2F;code&gt;&lt;br &#x2F;&gt;
We are a non-profit tech startup building an education-focused platform to aggregate data from various integrations (Learning management systems),
in which incarcerated students can access their coursework and grades, and correctional facilities can track their progress across
multiple providers. The original product was developed in the MO state prison system by a handful of residents, and was written in PHP 5.6,
with no internet access, no stack overflow, and no real-world development experience. It was truly impressive to see the result of this,
and I am surprised to this day how much they were able to accomplish with such limited resources. This was the reason PHP was chosen as the
primary language for version 2 of the platform.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;The Good:&lt;&#x2F;code&gt;&lt;br &#x2F;&gt;
Since I had been away from the tech world for so long, I missed out on most &#x27;frameworks&#x27;. Rails was just blowing up when I was programming last,
so I never got much experience with the concept of an HTTP server being abstracted away from the developer. Back then a lot of the PHP was inline in the HTML, and you just thought about the whole process differently. I soon realized that nearly every single thing you might want to do, Laravel not only had thought of it, but seemed to have a command that generates the necessary code to do it.
If I had realized this sooner, I would have had a much more smooth experience with the platform. Unfortunately I spent the first few months trying to solve
a lot of the common problems by hand first, before realizing that Laravel had a highly opinionated way of doing things, and that it was best to just
follow the conventions. I&#x27;m not against an opinionated approach, in fact it&#x27;s one of the things I like most about Go.&lt;&#x2F;p&gt;
&lt;p&gt;Overall, Laravel, for me, is much more accessible than a framework like Django, which completely abstracts away any concept of a server
(if you aren&#x27;t a django developer, and you were to see a django codebase for the first time, I&#x27;d be willing to bet pretty much whatever that
unless you studied it pretty thoroughly and did some google&#x27;ing, you couldn&#x27;t tell me it&#x27;s an http server). Laravel has the straight forward and easily identifiable concepts you would expect, the ORM is actually pretty good, assuming you can configure your LSP and linter
to properly recognize the methods, and the built-in migration system is easy to use. All in all, as far as frameworks go,
Laravel is surprisingly good, and for a blog or simple e-commerce website, I&#x27;d take it over NextJS or Django any day (I&#x27;m not a Ruby dev so I can&#x27;t speak on Rails).&lt;&#x2F;p&gt;
&lt;p&gt;Modern PHP is &lt;em&gt;very&lt;&#x2F;em&gt; different from the PHP of old. It has some surprisingly good language features like Traits and match statements, however their enums are in competition with typescript for being the worst of any language I have seen. Modern PHP manages to take a rather straight-forward object oriented approach, at a bit more than the level of python. My personal preferences lean much heavier into the functional realm, so I was pleased to find that PHP now also provides some basic functional features too, like their &#x27;iterator&#x27; package.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;The Bad:&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;First lets go with the obvious... C++ and JS share this issue as well: backwards compatibility has just kept so much suspect nonsense in the language, that you are stuck trying to figure out which of the 4 ways to do X thing you should be using. PHP&#x27;s problem in particular, is that they seem to have switched the naming convention each time they designed one of these bad features, so you will often find a lower_snake, Pascal, camelCase, ... versions of a slightly different named function and be stuck with that mess for a while. I don&#x27;t know if they switched the global naming convention every 5 years, but damn is there some inconsistency there.&lt;&#x2F;p&gt;
&lt;p&gt;Another fairly obvious one: I am heavily on team &quot;strongly and staticly typed languages are better&quot;, I write Rust in my free time on all my hobby or contract projects. Now,
after having worked with PHP and Laravel for about 8 months, I can say that I am even more convinced. You may be able to write plenty of larger,
more complex applications in Laravel with no problems, however
if one day you need to perform a non-trivial refactor, you will be in for a rough time.&lt;&#x2F;p&gt;
&lt;p&gt;Some of the most common issues I have had with Laravel are the fact that because
Laravel takes care of so many common things for you, you will define things like &lt;code&gt;Requests&lt;&#x2F;code&gt; and &lt;code&gt;Resources&lt;&#x2F;code&gt;, that come with methods on them validate the
JSON bodies or serialize the returned database rows into a JSON response. This is all well and good, but many applications will have several Request and
Resource types for each controller, and if you have multiple rows&#x2F;fields change on each table, you will be having to edit files like these across many parts
of your application. Anything you may miss, static typing will easily catch at compile time.&lt;&#x2F;p&gt;
&lt;p&gt;&quot;Dynamic types are fine, testing fixes this problem...&quot;
&lt;img src=&quot;&#x2F;pepe_cope.png&quot; alt=&quot;copium&quot;&#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;PHP&#x27;s linter and LSP are simply sub-par compared to what you
are going to get with &lt;code&gt;Gopls&lt;&#x2F;code&gt; or &lt;code&gt;Rust-Analyzer&lt;&#x2F;code&gt;, or even something like &lt;code&gt;TSServer&lt;&#x2F;code&gt;. This isn&#x27;t necessarily a PHP or even an issue with Laravel, but
the introspection tools are just not able to handle the complex types that you are working with in Laravel. Simply setting up a good linter
took hours because it would throw errors on lots of valid code, and I had to outright disable it for certain files. (skill issue, I know. but I want the linter to just work)&lt;&#x2F;p&gt;
&lt;p&gt;Yes, PHP 8+ has some type hinting, but there is no compile time to enforce them at, so much of the usefulness is lost. I have had handlers where there was (declare(strict_types = 1)), declared:
that didn&#x27;t throw errors until that specific handler had been called.&lt;&#x2F;p&gt;
&lt;p&gt;Now, Go&#x27;s type-system is far from perfect, and it&#x27;s famous lack of type safe enums&#x2F;unions makes me cry a little bit inside.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;type&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;const&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;  Red&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;  Blue&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;  Green&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; applyColor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; doSomethingWithColor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;color&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;  &#x2F;&#x2F;...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;func&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  var&lt;&#x2F;span&gt;&lt;span&gt; num&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 2340&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;  applyColor&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;num&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;  &#x2F;&#x2F; nothing wrong with this!, no problems here!   💀&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Although this is far from my only issue with Go, (I&#x27;m looking at you, single letter variable naming convention -_- ) &lt;code&gt;(w http.ResponseWriter, r *http.Request)&lt;&#x2F;code&gt;,
modules, and capital-letter for public access... and mayyybe some more issues I won&#x27;t get into right now 😅&lt;&#x2F;p&gt;
&lt;p&gt;But what we did gain, on top of performance, type safety, long-lived processes, simpler deployments and the ability to move some functionality into independent services, was a very clear intention in our back-end of what is really happening. Go&#x27;s stdlib &lt;code&gt;net&#x2F;http&lt;&#x2F;code&gt; imho, is the &lt;em&gt;perfect&lt;&#x2F;em&gt; amount of abstraction
for writing most servers. It would be impossible to write back-ends in Go, and not have a solid fundamental understanding of what is going on. You are not
simply figuring out X framework&#x27;s particular method of solving Y end-user problem, you are implementing the actual solution to it, by understanding
what needs to happen.&lt;&#x2F;p&gt;
&lt;p&gt;Random example:&lt;&#x2F;p&gt;
&lt;p&gt;Lets go with basic auth middleware. Many projects rely on some outside service (we actually do now rely on &lt;code&gt;Ory&lt;&#x2F;code&gt; because we needed comprehensive identity mgmt for the environment), but still employ the good old JWT.&lt;&#x2F;p&gt;
&lt;p&gt;In Go, a popular way of implementing auth would be to install the &lt;code&gt;JWT&lt;&#x2F;code&gt; module, and create a &lt;code&gt;Claims&lt;&#x2F;code&gt; struct with some user + session information, encrypt it,
and set the cookie in the browser. Then you make some middleware (which is exactly what you would think it would be, a function that accepts a handler, and returns a handler), to check the cookie, validate the JWT, and create a &lt;code&gt;context.Context&lt;&#x2F;code&gt; key value pair with the claims you can pass around to subsequent
handlers, to make the relevant user session information available where you will need it.&lt;&#x2F;p&gt;
&lt;p&gt;This is a good example of how you are just forced to solve the problem itself, as opposed to trying to figure out exactly how to use X frameworks particular abstraction layer, having to read their docs and make sure you are doing all the
required things in the right order to make this work. In Go, you are thinking about how to solve the specific problem of needing to validate each
request sent by the user, and it forces you to understand what is really happening behind the scenes. I find often times that the problem itself is far more trivial than trying to figure out how to use the API of whatever &#x27;solution&#x27; is being sold to you as a convenience. This leaves newer developers clueless as to how these things are actually implemented, and only teaches them how to use X tool.&lt;&#x2F;p&gt;
&lt;p&gt;Yes I know that this argument could be applied all the way down the stack, eventually ending in the semi brainrot argument of &quot;you have to use only C or assembly for everything or it&#x27;s a skill issue&quot; that&#x27;s been popular in some programming circles lately with the seemingly unemployed. But this is the particular layer where I&#x27;ll pick my personal hill to die on.&lt;&#x2F;p&gt;
&lt;p&gt;This abstraction level is fine for the majority of the web applications, and unless you need extreme performance, Go will serve quite well
as a versatile, fast and simple back-end or service. Go services can easily run in &lt;code&gt;scratch&lt;&#x2F;code&gt; docker containers with almost no dependencies.
Deployments and development environments are very simple as everything integrates well in the docker&#x2F;container ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;Production php&#x2F;laravel deployments are significantly more work and preparation, and you can say that containerizing is cheating, but
even container free I am able to deploy our Go application on an &lt;code&gt;ec2&lt;&#x2F;code&gt; in 1&#x2F;4 of the time it would take me to deploy our old codebase.&lt;&#x2F;p&gt;
&lt;p&gt;That is enough of my rant for today. These aren&#x27;t two languages that are commonly&#x2F;should be compared as they have very little in common,
so I am not trying to do too much here. Overall I am much happier getting to work with Go every day over php, and so far it has been
a great experience.&lt;&#x2F;p&gt;
&lt;p&gt;Does PHP suck as much as people say? No, definitely not.&lt;&#x2F;p&gt;
&lt;p&gt;Do I particularly want to use it for anything more complex than a blog or simple application? No, probably not.&lt;&#x2F;p&gt;
&lt;p&gt;At least with php, nobody is trying to use it for anything outside of it&#x27;s intended domain. 🥲&lt;&#x2F;p&gt;
&lt;img src=&quot;&#x2F;js_server.png&quot; alt=&quot;mistake&quot;&#x2F;&gt;
&lt;p&gt;Thanks for reading this, questions or comments feel free to email me at &lt;code&gt;preston@pthorpe92.dev&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Gratitude</title>
          <pubDate>Mon, 13 Nov 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/gratitude/</link>
          <guid>https://pthorpe92.dev/gratitude/</guid>
          <description xml:base="https://pthorpe92.dev/gratitude/">&lt;p&gt;&lt;code&gt;How I got here&lt;&#x2F;code&gt; is already far too long of a post, so I must include this for all the credits and gratitude I need to extend to those who made this possible.&lt;&#x2F;p&gt;
&lt;p&gt;To my parents: who supported me every single day of the decade+ I have spent behind bars, and who never gave up on me, even when I definitely deserved it and had well past given up on myself.&lt;&#x2F;p&gt;
&lt;p&gt;To Mark Spahr and Rachel Mclean Who I work with in the Education Technology department, who gave me a chance to prove myself, and without whom I would never have had any of the access or resources I needed to gain the skills, knowledge and experience that I have today. I owe virtually all of my success to them for giving me the opportunity.&lt;&#x2F;p&gt;
&lt;p&gt;To Haley, Jessica, Nokie and the entire team&#x2F;family at UnlockedLabs. Definitely the only company that was going to do anything with my resume but chuckle and throw it away. I couldn&#x27;t be more proud to be part of the team.&lt;&#x2F;p&gt;
&lt;p&gt;To Laura Rodas (Education Director), and Randy Liberty (Commissioner of the MDOC) and all who approved the policies that make things like this possible.&lt;&#x2F;p&gt;
&lt;p&gt;and finally I just want to throw a thank you to Andreas Kling and The Primeagen, who I have been following for a long time, but who will most likely never read this, but nevertheless who inspired me with their stories and their work and who I look up to very much. I have been clean and sober for well over 4 years now, and it&#x27;s not easy in this environment. It has been a huge inspiration to see success stories of others that have gone through addictions.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>OCaml + Rust: some comparisons</title>
          <pubDate>Sun, 12 Nov 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/ocaml-some-rust-comparisons/</link>
          <guid>https://pthorpe92.dev/ocaml-some-rust-comparisons/</guid>
          <description xml:base="https://pthorpe92.dev/ocaml-some-rust-comparisons/">&lt;p&gt;Following up on the first impressions post, let&#x27;s solve a
problem in OCaml and compare the Rust solution.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;in-response-to-how-well-received-my-last-post-was&quot;&gt;&lt;em&gt;In Response&lt;&#x2F;em&gt; to how well received my last post was&lt;&#x2F;h4&gt;
&lt;p&gt;I thought I would follow up with some comparisons between how I would solve a simple problem (Advent of code 2022, day 3 part 1) in both languages and compare the solutions, while trying to portray the kind of thinking required (I think anyway) to begin to solve problems in (OCa)ml style languages.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The only thing I will say first.. is these kind of simple
questions do not lend themselves to great comparisons,
because someone well versed in their language of choice, will
be much more likely and able to just solve the problem in a
neat, concise, way probably in a single function&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;the-problem&quot;&gt;The Problem&lt;&#x2F;h3&gt;
&lt;p&gt;I&#x27;m not going to bother with the story, if you are interested,
you can read it &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;adventofcode.com&#x2F;2022&#x2F;day&#x2F;3&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I will also be leaving out the reading in of the file, as
it isn&#x27;t specific to this problem, and everyone will usually
have an &#x27;aoc&#x27; page of helper fn&#x27;s for this anyway.&lt;&#x2F;p&gt;
&lt;h5 id=&quot;the-basics&quot;&gt;The Basics&lt;&#x2F;h5&gt;
&lt;p&gt;We need to take a string, split it in half, and then find the&lt;&#x2F;p&gt;
&lt;p&gt;one single char that occurs in both substrings, and sum the val&lt;&#x2F;p&gt;
&lt;p&gt;given to each char (a-z = 1-26) (A-Z = 27-52)&lt;&#x2F;p&gt;
&lt;p&gt;Pretty simple right? If it wasn&#x27;t for assigning the values to&lt;&#x2F;p&gt;
&lt;p&gt;chars (or if they were just ascii values), then I&#x27;d say that&#x27;s&lt;&#x2F;p&gt;
&lt;p&gt;a good-ol&#x27; &lt;code&gt;python one-liner&lt;&#x2F;code&gt; if I ever saw one.&lt;&#x2F;p&gt;
&lt;p&gt;For the sake of simplicity. We need:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;vJrwpWtwJgWrhcsFMMfFFhFp&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;to split into:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(&amp;quot;vJrwpWtwJgWr&amp;quot;, &amp;quot;hcsFMMfFFhFp&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      ^                      ^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;p is the char that occurs in both substrings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     the value of p is 16&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;we simply add this value for each original string.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h4 id=&quot;because-i-am-an-ocaml-n00b&quot;&gt;Because I am an Ocaml n00b&lt;&#x2F;h4&gt;
&lt;p&gt;We will break this up into 3 simple functions (and a main), and &lt;em&gt;try&lt;&#x2F;em&gt; to
solve the problem in relatively the same steps in &lt;em&gt;both&lt;&#x2F;em&gt; languages,
so we can give them a &lt;code&gt;fair&lt;&#x2F;code&gt; comparison of basic operations.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Split the list of strings, into a list of tuples.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;With that input, find and return the suspect char.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Perform some lookup or calculation to get and sum the values of the chars.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Call these from a main function + print to stdout.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;🦀 🦀&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; *** We iterate over the list of strings, split and collect into vec of tuples ***&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; split_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;line&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span&gt; mid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;first&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; second&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;split_at&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;mid&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;            (&lt;&#x2F;span&gt;&lt;span&gt;first&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; second&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; *** Find the character that occurs in both substrings ***&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; find_dupe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;find&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; *** Map the char to its value ***&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; map_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;is_lowercase&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;        (&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;z&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; &#x2F;&#x2F; enumerate gives us index, value so we return the index + 1 for the char&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;find_map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;        (&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;..=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;#39;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;enumerate&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;find_map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;            .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; std&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;input&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; file&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;split&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5BDE6;&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;&amp;#39;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; spltlines&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; split_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; total&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; spltlines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;            if let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; find_dupe&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;) {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;                map_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;            }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;                0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;        })&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;  println!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;total&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; As I&amp;#39;m sure some will point out, we definitely could have made this a lot more concise&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; But for the sake of comparison, we will leave the naive implementation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So this was a touch more painful than I thought it would be...
Forcing myself to split those up into three different functions
when I would normally for such a simple problem just cram it all
into one, being able to operate more by chaining iterators.&lt;&#x2F;p&gt;
&lt;p&gt;But I think you could definitely come up with worse examples.&lt;&#x2F;p&gt;
&lt;p&gt;Time for the 🐫&#x27;Caml 🐪&lt;&#x2F;p&gt;
&lt;p&gt;For those of you who aren&#x27;t familiar with Ocaml, I&#x27;ll try to briefly
explain my very limited understanding.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;(* In Ocaml, functions from other modules are called with &amp;#39;Module.fn&amp;#39; syntax,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;so String.length is the length fn from the String module. I do like how Mod&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;names are capitalized, instead of the public fn name like in Go. *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;(* Here we have a recursive function(denoted by the rec keyword)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;called &amp;#39;split_string&amp;#39; that takes our input lst, and an&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;accumulator (an empty list in which to put the result: our tuples) *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; split_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;lst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  match&lt;&#x2F;span&gt;&lt;span&gt; lst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; hd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;tl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;length hd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;              let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; substr_a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sub hd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;              let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; substr_b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sub hd len len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;              split_string tl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; ((&lt;&#x2F;span&gt;&lt;span&gt;substr_a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; substr_b&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;(* We pattern-match on the list, and while there is still some strings remaining,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;we get the length of the string(hd) and then call String.sub on(which takes the string,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;the position at which the substring starts, and the length of the substring) to split&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;it into the tuple. we append the tuple to the accumulator with the &amp;#39;cons&amp;#39; :: operator&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;and then call the function recursively with the accumulator + the remainder of the list*)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;------------------------------------------------------------------------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;(* Here we have a function with no parameters that simply computes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;the integer values of lower+uppercase chars and creates a (key val) style list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;of (char int) tuples e.g. (&amp;#39;p&amp;#39;, 16) (&amp;#39;q&amp;#39;, 17)... so pretty much seems to me like a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;super inefficient hashmap. I&amp;#39;m sure all you OCaml wizards are cringing rn *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; char_to_int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; ()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; mapping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; acc start_char end_char value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; start_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; end_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      mapping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; ((&lt;&#x2F;span&gt;&lt;span&gt;start_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;Char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;chr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;Char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;code start_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;))&lt;&#x2F;span&gt;&lt;span&gt; end_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; lower&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; mapping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;a&amp;#39; &amp;#39;z&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; upper&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; mapping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span&gt; &amp;#39;A&amp;#39; &amp;#39;Z&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 27&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;  List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rev_append lower upper&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;(* We call that function, and then use List.assoc to get the value in our key, val tuple *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; char_to_int_mapping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; char_to_int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; ()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; find_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; char_to_find&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  try&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;assoc char_to_find char_to_int_mapping&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt;    Some&lt;&#x2F;span&gt;&lt;span&gt; result&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  with&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; Not_found&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-------------------------------------------------------------------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;(* Simple function to find the char between the two substrings, utilizing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; String.fold_left which allows us to apply a fn on each char of a string,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;so we call Strings.contains on the other string on each char, and append it *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; find_common_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;s1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; s2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; common_chars&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;    String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fold_left&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;      (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; acc c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; if&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;contains s2 c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; then&lt;&#x2F;span&gt;&lt;span&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt;      []&lt;&#x2F;span&gt;&lt;span&gt; s1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  match&lt;&#x2F;span&gt;&lt;span&gt; common_chars&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; None&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; common_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span&gt; common_char&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;(* Another recursive function to sum up the values of the chars. we cheated in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;rust by having this in the main fn. but notice how, here we cannot call&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;.unwrap_or() or similar fn&amp;#39;s, we must pattern match *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; sum_vals&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;lst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;) (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  match&lt;&#x2F;span&gt;&lt;span&gt; lst&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; sum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;  |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; hd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;tl&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      sum_vals tl sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;        match&lt;&#x2F;span&gt;&lt;span&gt; find_common_char hd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;            |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;            |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; ch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; match&lt;&#x2F;span&gt;&lt;span&gt; find_value ch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; with&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;                        |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;                        |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; None&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; lines&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; split_lines&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;read_lines&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;quot;input&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; ans&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; sum_vals lines&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;print_int ans&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;(*^ Here would be our main fn, we are just calling the above functions, read_lines&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;is the helper fn that reads the file in to a list of strings *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, I&#x27;m sure that was a mess, but I have only been messing with the &#x27;Caml for a
couple weeks now. Please feel free to hit me up with corrections&#x2F;pointers
if you are an Ocaml wizard, I&#x27;d love to learn as much as I can. You&#x27;ll have to
email me though, am I far too lazy to setup sqlite for comments.&lt;&#x2F;p&gt;
&lt;p&gt;I imagine that as I get more comfortable with the standard library I will
end up using built in features where currently I might use recursion. However I am starting
to enjoy the style and find it quite satisfying to produce an effective recursive solution.&lt;&#x2F;p&gt;
&lt;p&gt;I haven&#x27;t yet looked into the other common data structures either, so I am sure
there are plenty of other improvements that can be made.&lt;&#x2F;p&gt;
&lt;p&gt;If you were unfamiliar with either language.. god help you, the whole post probably looked
pretty scary depending on what background you have.&lt;&#x2F;p&gt;
&lt;p&gt;As I have learned a tiny bit more, it is definitely growing on me, and tasks
I was tripping over even a few days ago are becoming a little more natural. The
farther I get, the more I realize the similarities and as I go on, whatever advantage
there might be from using a language that was heavily influenced by it,
will probably start to show more and more.&lt;&#x2F;p&gt;
&lt;p&gt;I hope to provide (maybe more concise next time) more of my journey and thoughts on the &#x27;Caml,
which I can say, I most definitely recommend to anyone who is interested in
challenging their idea and perception of programming, while getting to learn a language
with some very different syntax but also some great FP concepts&#x2F;features that
is actually used outside of Academia (Haskell we&#x27;re looking at you)&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Note: This is meant to be a comparison to show people who are interested in learning 🐫
just some of the initial differences, and structure, to see what their experience might be like,
as they begin to play around with the language.
I try to learn every day, and the more that I learn, the more I realize that I am an expert at nothing.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Thanks for reading this, feel free to reach out to me if you are interested in discussing these
topics, or if you have any corrections&#x2F;pointers for me. I can be found on the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;eza-community&#x2F;eza&quot;&gt;eza&lt;&#x2F;a&gt; &lt;a href=&quot;eza:gitter.im&quot;&gt;matrix&#x2F;gitter&lt;&#x2F;a&gt; channel.
or you can email me at &lt;a href=&quot;mailto:p@eza.rocks&quot;&gt;p@eza.rocks&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;blockquote&gt;
&lt;p&gt;EDIT:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h1 id=&quot;a-solution-from-an-actual-ocaml-programmer&quot;&gt;A solution from an &lt;em&gt;actual&lt;&#x2F;em&gt; OCaml programmer&lt;&#x2F;h1&gt;
&lt;p&gt;This excellent, concise solution was emailed to me by Yawar Amin &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yawaramin&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;yawaramin&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;(after finding him on github, it became immediately obvious that he is indeed, one of the before-mentioned OCaml wizards)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #ED8796;&quot;&gt;module&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; SC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; Set&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;Make&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;Char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; (* Module for set of char *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; prio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; ch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; Char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;code ch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span&gt; code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 97&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; then&lt;&#x2F;span&gt;&lt;span&gt; code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 96&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; (* a-z *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  else&lt;&#x2F;span&gt;&lt;span&gt; code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 38&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; (* A-Z *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; common&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;length string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; half_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; first&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; SC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;of_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;to_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sub string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span&gt; half_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; second&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; SC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;of_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;to_seq&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;String&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;sub string half_len&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;half_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;))&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; common_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; SC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;inter first second&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; (* Set intersection *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;  assert&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;SC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;cardinal common_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; (* Assert set contains only&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt;one member *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;  SC&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;min_elt common_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; (* Min element must be the common character *)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; common_prio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; |&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; common&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; |&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; prio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fold_left&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; sum string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span&gt; common_prio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This clearly takes advantage of data structures in the standard library that I have not yet explored. (Obviously it&#x27;s implementation of &lt;code&gt;Set&lt;&#x2F;code&gt;, but also &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;v2.ocaml.org&#x2F;api&#x2F;Seq.html&quot;&gt;seq&lt;&#x2F;a&gt;): A &lt;code&gt;seq&lt;&#x2F;code&gt; or sequence is type of list that is lazily evaluated, increasing performance but also allowing for things like conceptually infinite sequences. I guess &lt;code&gt;sequences&lt;&#x2F;code&gt; are found in Haskell and F# (called a &lt;code&gt;stream&lt;&#x2F;code&gt; in Scala), and can be best compared to Iterators in Rust. This sending me down a pretty deep rabbit hole that could take up a whole if not several posts, learning about the use of &lt;code&gt;lazy&lt;&#x2F;code&gt;, &lt;code&gt;seq&lt;&#x2F;code&gt;, and &lt;code&gt;iter&lt;&#x2F;code&gt;, and the differences between them.&lt;&#x2F;p&gt;
&lt;p&gt;I think this highlights one of the hurdles of a new paradigm, is it forces you to almost hyper focus on trivial tasks, causing you to forget the bigger picture, and not reach for the tools you would in other languages.&lt;&#x2F;p&gt;
&lt;p&gt;For the sake of keeping with the nature of the post: I thought I would try to implement the &lt;em&gt;exact&lt;&#x2F;em&gt; same solution in Rust, mimicking it as closely as possible. (fn names and all)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; prio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;ch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; ch&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; as u32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span&gt; code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &amp;gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 97&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;        (&lt;&#x2F;span&gt;&lt;span&gt;code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 96&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; as i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; &#x2F;&#x2F; a-z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; else&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;        (&lt;&#x2F;span&gt;&lt;span&gt;code&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 38&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; as i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; &#x2F;&#x2F; A-Z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; common&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; half_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; first&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;half_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; second&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;skip&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;half_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;take&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;half_len&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; common_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; HashSet&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; first&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;intersection&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt;second&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;cloned&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;    *&lt;&#x2F;span&gt;&lt;span&gt;common_char&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;next&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt; &#x2F;&#x2F; Min element must be the common character&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;font-style: italic;&quot;&gt;&#x2F;&#x2F; To demonstrate &amp;#39;|&amp;gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; common_prio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;: &amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;    prio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;common&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;&quot;&gt;list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;str&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;fold&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt;0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; |&lt;&#x2F;span&gt;&lt;span&gt;sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; sum&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; +&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; common_prio&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;() {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; strings&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; fs&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;read_to_string&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;input&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; splitstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; strings&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;lines&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;()&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;_&lt;&#x2F;span&gt;&lt;span style=&quot;color: #91D7E3;&quot;&gt;&amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;();&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span&gt; result_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; result&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;splitstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;Result: &lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;{}&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; result_value&lt;&#x2F;span&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;);&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #939AB7;&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Notice how awesome the &lt;code&gt;|&amp;gt;&lt;&#x2F;code&gt; operator is in OCaml (the &quot;pipe&quot; operator, as it&#x27;s so appropriately called), and what the same thing looks like in Rust. (Really any C based lang, but here in Rust, and unless you were to implement trait methods and then chain them).&lt;&#x2F;p&gt;
&lt;p&gt;Seeing the comparison really makes me appreciate the functional style even more. Big thank you to Yawar for the solution 👍.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Hackers guide to the hackernews front page</title>
          <pubDate>Fri, 10 Nov 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/hackers-guide-to-hn-front-page/</link>
          <guid>https://pthorpe92.dev/hackers-guide-to-hn-front-page/</guid>
          <description xml:base="https://pthorpe92.dev/hackers-guide-to-hn-front-page/">&lt;p&gt;Humorous article, completely unrelated to, and written before, the others ended up actually on the front page.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-goal&quot;&gt;&lt;strong&gt;The Goal:&lt;&#x2F;strong&gt;&lt;&#x2F;h1&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;To get a post on the front page of the infamous Orange site...&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;the-plan&quot;&gt;&lt;strong&gt;The Plan:&lt;&#x2F;strong&gt;&lt;&#x2F;h1&gt;
&lt;hr &#x2F;&gt;
&lt;ul&gt;
&lt;li&gt;There are four guaranteed strategies. No one knows why they work, but you may pick one, give it a shot, and tell me I&#x27;m wrong.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;option-1&quot;&gt;Option 1:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Put &lt;strong&gt;RISC-V&lt;&#x2F;strong&gt; in the title.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;blockquote&gt;
&lt;p&gt;That&#x27;s it. I don&#x27;t care what else the title says, it could be announcing that you have the rear bumper of a 1971 Chevette for sale,
that shit is on a rocket-ship straight to number 1.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h3 id=&quot;option-2&quot;&gt;Option 2:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;code&gt;wikipedia.com&lt;&#x2F;code&gt;, to the &#x27;search&#x27; bar, and proceed to allow your cat to walk across on your keyboard several times back and forth..&lt;&#x2F;p&gt;
&lt;p&gt;Do this until some semblance of an english word or phrase appears in the text-box, then press the Search button. Now, you may need to do this
multiple times because the first initial results might not be odd or eccentric enough.&lt;&#x2F;p&gt;
&lt;p&gt;Perhaps try your other cat, or if you do not have another cat
in your household, go find a neighborhood cat, and entice him&#x2F;her&#x2F;they to traverse your keyboard.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I have heard that &lt;code&gt;dvorak&lt;&#x2F;code&gt; keyboards may be superior for this, although I must admit I heard it from an Uber driver so I&#x27;m not going to risk my
internet reputation and tell all of you like it&#x27;s a fact.. It&#x27;s not like I read it on wikipedia &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=dQw4w9WgXcQ&amp;amp;pp=ygUIcmlja3JvbGw%3D&quot;&gt;article*&lt;&#x2F;a&gt;. We will have to ask ThePrimeagen to confirm this.&lt;&#x2F;p&gt;
&lt;p&gt;The best way to provoke this behavior from cats, is to appear to the cat, that you are in an important &#x27;zoom&#x27; meeting, or are otherwise occupied on your computer
doing some task that would be greatly impeded by said feline should they decide to go for a stroll down &lt;em&gt;qwerty&lt;&#x2F;em&gt;-lane.&lt;&#x2F;p&gt;
&lt;p&gt;You will know when the search results are right, because the topic will be so obscure, that you will sit back in awe of who could possibly have
thought that this information was relevant or important to anyone else, while still sounding like something that, if someone told you Columbia university
pays 14 million dollars a year in grant money to research, you wouldn&#x27;t second guess it.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;option-3&quot;&gt;Option 3:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;Link to an Open source project&#x2F;technology that is old enough at this point that you might even consider leaving it off your resume, but not so old that it gets caught up with the hundreds of posts every day that simply link to the clearly still-maintained website of some ancient technology from 1962; that somehow looks like the website too, was designed in the same time period, in preparation for the eventual release of the internet.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Some suggestions:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;pthorpe92.dev&#x2F;hackers-guide-to-hn-front-page&#x2F;blosxom.sourceforge.net&#x2F;&quot;&gt;Blosxom&lt;&#x2F;a&gt;  (I shit you not, as I was google&#x27;ing for this, &lt;img src=&quot;&#x2F;blosxom.png&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zope.dev&quot;&gt;Zope&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;coffeescript.org&#x2F;&quot;&gt;CoffeeScript&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;XHTML&quot;&gt;XHTML&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tomcat.apache.org&quot;&gt;Apache Tomcat&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;option-4&quot;&gt;Option 4:&lt;&#x2F;h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ShowHN:&lt;&#x2F;strong&gt; Build something in the upper left corner of a chart where complexity and difficulty is the Y axis and real-world usefulness is its X.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Some recommendations are:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;A common-lisp to vimscript-8 transpiler.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Rewrite any of the coreutils in Javascript.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;A web framework in APL (or your choice of array language).&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Implement (at least some part of) the &lt;em&gt;JVM&lt;&#x2F;em&gt; in a scripting language&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Implement either &lt;em&gt;Flappy Bird&lt;&#x2F;em&gt; or &lt;em&gt;Conways game of life&lt;&#x2F;em&gt; in your choice of:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;GNU Sed, Bash, elisp, etc. Just ask yourself, if Richard Stallman was going to implement flappy bird...&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;The Typescript Typesystem&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Inside a computer you build inside a video-game (minecraft, etc)&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Dreamberd&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;*You know, that for just a moment... you believed that it was a real article..&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for reading this, I had a laugh writing it.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Ocaml: first impressions</title>
          <pubDate>Thu, 09 Nov 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/ocaml-first-thoughts/</link>
          <guid>https://pthorpe92.dev/ocaml-first-thoughts/</guid>
          <description xml:base="https://pthorpe92.dev/ocaml-first-thoughts/">&lt;h4 id=&quot;the-why&quot;&gt;The Why&lt;&#x2F;h4&gt;
&lt;p&gt;I&#x27;m somewhat of a language nerd to begin with, and it was Rust that originally got me interested in the whole functional paradigm.
Not due to it&#x27;s lineage, but the heavy use of chained iterator methods in favor over traditional loops. This is one of the more intimidating hurdles
for newcomers to the language, but after getting used to it, rarely will you see anyone write a &lt;code&gt;for&lt;&#x2F;code&gt; loop again.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Rant:&lt;&#x2F;strong&gt; The argument can be made that what I&#x27;m talking about is more similar to Javascript-land where a bunch of pseudo-functional methods and terminology are
used, but it in reality is as far away from functional programming as &lt;code&gt;useState()&lt;&#x2F;code&gt; would imply it is.
At least Rust has a few things to back it up, as at least a language that will support you should you desire to write pure functional code. I would argue that for beginners, Rust will simply force you to write functional, immutable code, whether they really understand it or otherwise, as the amount of &lt;code&gt;.clone()&lt;&#x2F;code&gt;&#x27;ing required for a newcomer to compile a non-trivial program will practically almost guarantee that nothing was actually &lt;code&gt;&amp;amp;mut&lt;&#x2F;code&gt;ated*.&lt;&#x2F;p&gt;
&lt;p&gt;So this got me interested in watching some &lt;em&gt;GOTO&lt;&#x2F;em&gt;, &lt;em&gt;strangeloop&lt;&#x2F;em&gt;, and other conference talks about functional programming. Upon discovering &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@artemslab&quot;&gt;@artemslab&lt;&#x2F;a&gt;
(definitely go check it out, absolutely &lt;em&gt;fantastic&lt;&#x2F;em&gt; high quality, very in-depth content) on YouTube and watching some videos, and reading about and it&#x27;s runtime integer representations and memory allocation, that really got me fascinated with the language. One of the programs that he demonstrates is a huge static analysis tool written in Ocaml, called &#x27;Infer&#x27;, that I had never heard of, but seeing the scale of this project and the adoption by some huge companies I was super impressed and even more excited to maybe build my next side project in Ocaml, if for nothing but the learning experience. (and possibly a little street cred in the Rust community, if I&#x27;m being honest ;)&lt;&#x2F;p&gt;
&lt;p&gt;In the past I typically wouldn&#x27;t hesitate to just &lt;code&gt;sudo pacman -Sy &lt;&#x2F;code&gt; whatever compiler or interpreter I needed, to get started playing around with whatever new language I was interested in. However since getting full-time employment, on top of the existing OSS stuff, as well as doing some contracted gigs for the facility I&#x27;m in, I haven&#x27;t had so much as a moment to spend on anything fun quite some time.&lt;&#x2F;p&gt;
&lt;p&gt;Anyways, as usual I&#x27;m off track here. My point is that I &lt;em&gt;thought&lt;&#x2F;em&gt; I had a good introduction to the world of FP, and I &lt;em&gt;thought&lt;&#x2F;em&gt; since I&#x27;d heard that many of the
features and some of the syntax we love from Rust came directly from tha &#x27;Caml itself, I thought I would love it immediately and thought perhaps picking it up would be at least as simple as picking up any other language and I could count on the same method I rely on.&lt;&#x2F;p&gt;
&lt;p&gt;Well, I think anyone who has tried to jump from C based languages to the &#x27;ml&#x27; or FP world, can probably tell you how foolish of a thought that was.&lt;&#x2F;p&gt;
&lt;p&gt;My plan was to do the entire Advent of Code in Ocaml, then I was going to pick an ambitious project that I would otherwise use Rust for, and simply force myself
to use Ocaml. I find this is the best way to learn a language, is just take on a project that is significantly more ambitious than your current skill level, and by the time you finish it, you&#x27;ll have not only saved yourself a bunch of wasted time on tutorials that aren&#x27;t actually teaching you anything but how to copy from someones screen in a youtube video, but you&#x27;ll have made something cool :D (hopefully).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;i-have-two-gripes-with-the-language-so-far&quot;&gt;I have two gripes with the language (so far)..&lt;&#x2F;h3&gt;
&lt;h3 id=&quot;where-are-the-types-eyes&quot;&gt;Where are the types? 👀&lt;&#x2F;h3&gt;
&lt;p&gt;I underestimated how much I would be thrown off by the fact that the types are &lt;em&gt;heavily&lt;&#x2F;em&gt; inferred, and are almost never explicitly declared, from what I can tell. I found that the combination of this and the strange syntax really screws me up, as now I am having problems inferring my &lt;em&gt;own&lt;&#x2F;em&gt; types at this point...&lt;&#x2F;p&gt;
&lt;p&gt;When dealing with lots of recursive functions, you find yourself looking up often at the function signature to view the parameters, but the concise syntax makes it difficult to mentally parse quickly.&lt;&#x2F;p&gt;
&lt;p&gt;Example, random code snippet from ocaml.org:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #CAD3F5; background-color: #24273A;&quot;&gt;&lt;code data-lang=&quot;ocaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; group&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; list sizes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; initial&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; size&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; size&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; sizes&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; prepend&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; p list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; emit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; l acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; aux&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; emit acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;      |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; emit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;      |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; as&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;         let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; if&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; then&lt;&#x2F;span&gt;&lt;span&gt; emit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; ((&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt; l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;                   else&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         aux&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; l acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; emit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span&gt; l&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; acc&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; acc t&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;    in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    aux emit&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span&gt; list&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; rec&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; aux&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; function&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; []&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt; [&lt;&#x2F;span&gt;&lt;span&gt;initial&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;concat_map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;prepend h&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;) (&lt;&#x2F;span&gt;&lt;span&gt;aux t&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; aux list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; complete&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt; List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;filter&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;for_all&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt;x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;font-style: italic;&quot;&gt; _&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;))&lt;&#x2F;span&gt;&lt;span&gt; all&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt; in&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;    List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: #F5A97F;font-style: italic;&quot;&gt;List&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;map snd&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;)&lt;&#x2F;span&gt;&lt;span&gt; complete&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8BD5CA;&quot;&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt;val&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; group&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; :&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; int&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EE99A0;font-style: italic;&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #8AADF4;font-style: italic;&quot;&gt; list&lt;&#x2F;span&gt;&lt;span style=&quot;color: #EED49F;font-style: italic;&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: #C6A0F6;&quot;&gt;fun&lt;&#x2F;span&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #A6DA95;&quot;&gt;;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Even when you learn what it actually going on here, and it makes immediate sense to you.. It must take a while before it becomes easier to read.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;remember-recursion-how-about-linked-lists&quot;&gt;Remember recursion? How about linked lists?&lt;&#x2F;h3&gt;
&lt;p&gt;Two things every Computer science student learns, and then are immediately told to never use again*...&lt;&#x2F;p&gt;
&lt;p&gt;Anything that can be done recursively can be done iteratively (and most optimizing compilers will replace your recursion anyway), and linked lists are slow and inefficient with modern CPU caches, and you should almost never use them (and if you&#x27;re a web dev, well, you just wouldn&#x27;t anyway).&lt;&#x2F;p&gt;
&lt;p&gt;You could describe Ocaml as a language that relies &lt;strong&gt;heavily&lt;&#x2F;strong&gt; on &lt;em&gt;both&lt;&#x2F;em&gt; of these things. This feels even more strange that it might seem it would, and I have
found myself stumbling on absolutely remedial tasks.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, there are libraries with other data structures, and there are in fact &lt;code&gt;for&lt;&#x2F;code&gt; loops (and even &lt;code&gt;while&lt;&#x2F;code&gt; loops), However I feel like I will end up learning more of the language and find that iterator methods will be used more so than any of these, much as in Rust.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-good&quot;&gt;The Good:&lt;&#x2F;h1&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Thought provoking. If you don&#x27;t believe there is anything to gain from being forced to think about something you do every day in a completely different way... well I&#x27;m surprised you made it this far into the post.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Awesome mixture of !significant-whitespace and !brackets. And how cool is the comment syntax? (* doesn&#x27;t it just feel like.. middle-eastern-ish *);;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Tooling: is way better than it has any right to be, considering the size of it&#x27;s user-base and community.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Great conversation starter, really cool and helpful community.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Lots more to learn for sure but these were my initial thoughts anyway, I do really want to like it so we will see how much that helps. I just definitely did not get the head-start I was expecting, but I don&#x27;t think that&#x27;s a negative thing it just means there is more to learn.&lt;&#x2F;p&gt;
&lt;p&gt;*obviously I know this isn&#x27;t true and an extreme exaggeration, but I thought it was funny. There&#x27;s always someone who will &#x27;well ackshually&#x27; you when
you think you&#x27;ve been completely clear.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keep-in-mind-this-is-simply-my-first-impression-i-will-be-continuing-to-learn-and-will-be-periodically-writing-some-updates-on-how-my-feelings-change&quot;&gt;Keep in mind, this is simply my first impression. I will be continuing to learn and will be periodically writing some updates on how my feelings change.&lt;&#x2F;h2&gt;
&lt;p&gt;Also, once again have to plug &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;@artemslab&quot;&gt;@artemslab&lt;&#x2F;a&gt;. Doesn&#x27;t have NEARLY enough youtube subscribers for how good the content is.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>How I got here</title>
          <pubDate>Tue, 07 Nov 2023 00:00:00 +0000</pubDate>
          <author>Unknown</author>
          <link>https://pthorpe92.dev/intro/my-story/</link>
          <guid>https://pthorpe92.dev/intro/my-story/</guid>
          <description xml:base="https://pthorpe92.dev/intro/my-story/">&lt;p&gt;My story, and how this is all possible&lt;&#x2F;p&gt;
&lt;h3 id=&quot;introduction&quot;&gt;Introduction&lt;&#x2F;h3&gt;
&lt;p&gt;My name is Preston Thorpe, I&#x27;m 31 years old and I&#x27;ve spent just under 10 years of my life in Prison (all for non-violent drug crimes.)
I am currently incarcerated at Mountain View Correctional Facility in Charleston, Maine. More importantly, far more importantly, I am a software developer,
open source maintainer, contributor and all around enthusiast. I love rust, linux, Neovim, Alacritty, Tmux, tiling window managers (DWM), and doing everything possible from the command line.&lt;&#x2F;p&gt;
&lt;p&gt;Idk who will even end up reading this, but thats the whole idea of blogs right? Ideally maybe the Primeagen will read it at some point,
I feel like it&#x27;s right up his alley. I have lots of respect for him, I really appreciate him sharing his own story and particularly the message
of working hard for what you want, and also to stay away from bullshit&#x2F;drugs. He has actually been a pretty big inspiration for me in the tech world
and I&#x27;ve been following him for over a year now. So on the off-chance that you&#x27;re reading this: Thanks for everything you do, you have been an enormous inspiration to me, and the only source of entertainment I&#x27;ve allowed myself for the last year+.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Anyway...&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The (relatively) short version: I was a stupid 17yr old computer geek, spending my highschool years in the &#x27;05-&#x27;09 warez and torrent scenes(r.i.p. oink.cd) and was kicked out of my parents house for being a stupid 17yr old like many kids are, but instead of ending up broke and homeless sleeping in my car or on couches (I did that for a bit too though), and coming back to Mom + Dad&#x27;s apologetic, as I&#x27;m sure was their plan; I ended up stumbling head-first into the world of the pre silk-road&#x2F;Dark-web internet wholesale drugs. This was a place where chemicals could be bought for pennies from sketchy companies in India, China, and there were vendors in Canada, Holland, Germany, etc that sold bulk of whatever you wanted all by email referral.&lt;&#x2F;p&gt;
&lt;p&gt;So instead of coming back home broke and apologetic, I ended up pretty deep into this and soon was making tens of thousands of dollars a week, very much unapologetically. At age 20, I was arrested the first time. I was caught with MDMA coming in the mail from Vancouver, and some marijuana coming from california (the latter of which is what I am currently serving my time for right now).&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Prison:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I have found that I adapt pretty well to just about whatever situation I happen to be put in, Prison was no different. Although, these people were very different
from the hippie&#x2F;raver&#x2F;music festival people I dealt with on the street. These people were hardcore addicts, who many of were into crimes and a lifestyle that I
had no part of. The thing about prison is that it has its own sub-culture, it&#x27;s own lingo, it&#x27;s own set of morality.. and this is enforced by an extremely negative
group-think, strict mindset that we are criminals: we hate cops, we hate rats, pedophiles, thieves(only if you steal from other inmates, you can steal whatever
you want from any grandma on the street) and anyone that has ever &quot;PC&quot;&#x27;d (asked for Protective Custody due to fear of violence from another inmate(s)).
This mindset is strictly enforced on everyone living in population, and spending a few years around such negativity will change anyone. In prison, there is
nothing to do: except get tattoos, work out, and wait for some kind of drama to unfold so you can either watch something go down, or participate in it.&lt;&#x2F;p&gt;
&lt;p&gt;A few years later, I left prison with $0 in my pocket (lawyers and commissary are expensive, and nobody pays you what they owe you when you come in),
to a rooming house with hallways that smelled like crack-smoke and were filled with parole officers and junkies. I was left with the difficult choice
of either living there and walking to a temp agency with hopes of making $10.50&#x2F;hour doing manual labor (without an ID or social security card at this point),
or getting on a bus to NYC to see some associates, and coming back in a week or so with $15-25k in my pocket and living in comfy luxury hotels until
I could rent an apartment... I chose the latter: and obviously, was back in prison after a short 14 months of addiction and misery.&lt;&#x2F;p&gt;
&lt;p&gt;I have been incarcerated now on this sentence since May of 2017, I came in with a terrible attitude, a terrible outlook on life, and no hope for my future.
I have spent almost 3 years all-together in 22-23hr solitary confinement over the years (10% of my life?), and at one point I had truly become one of the people
that looked at me when I first came to prison at age 20, and asked &quot;Is this your first bid?&quot;, to which everyone replies &quot;first? I&quot;m not coming back here!&quot;,
to which there is always laughter from the older heads. Everyone says that, but everyone comes back...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Growing up:&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;My poor behavior and the perceived &#x27;influence&#x27; I had in the relatively small prison system that I came from, ended up getting me put on an inter-state transfer list
after 13mo in solitary confinement (for no disciplinary action.) &quot;Safety and security of the facility&quot; is the official reason it says on my classification
paperwork. Little did I know, this would be the single best thing that would ever happen to me.&lt;&#x2F;p&gt;
&lt;p&gt;Because I had no disciplinary action, and I guess very some fortunate timing, I got transferred to Maine, which is not a state that I thought was even
an option as it does not have a reputation for taking &#x27;problem&#x27; inmates from other states.&lt;&#x2F;p&gt;
&lt;p&gt;The prison system in Maine is different from all others, as the inmate population is insulated from most of the street&#x2F;prison gangs that generally run
things. Not having to deal with the Politics and the drama was refreshing, and a bit of a shock at first. Quickly I realized that my time could just be
spent on myself, trying to improve my life or just do what I wanted with my time. I began to focus my time on things like teaching myself about organic chemistry, and finance, options trading, and I began for the first time to realize that I might be capable of more than what I had resided on, and that I could end doing whatever I put my mind to.&lt;&#x2F;p&gt;
&lt;p&gt;I had previously accepted my fate, as one must when you get a 10+ year sentence, otherwise you&#x27;ll go insane constantly thinking about what you could have done different or what you could have been doing with your life. But I had accepted my fate, as a criminal. I had accepted the identity, and the lifestyle, and the misery, and the mindset that comes along with it.&lt;&#x2F;p&gt;
&lt;p&gt;One day, I woke up and looked around me, and had what can only be described as an epiphany. All of a sudden, all the conversations I would hear about drugs
and war stories, all just sounded like absolute bullshit to me, and I was suddenly ashamed that I ever participated in it. From that point, I no longer
felt like it was okay or normal that I was locked up in a cage, and the acceptance and self-identity as being a &#x27;criminal&#x27; no longer felt like something
I was okay with.&lt;&#x2F;p&gt;
&lt;p&gt;When it was available to me, I enrolled in College through the University of Maine Augusta, and before classes even started, I was completely enthralled
with the idea of learning how to program again (it had been 15 years since I had done some PHP&#x2F;Perl + simple websites, so not a lot had left over).
But wait.. Who else has an opportunity to spend 12+ hours a day learning something for years? With no other obligations or responsibilities? It all of a
sudden clicked, that I would dedicate the remainder of my time to learning everything I could about computer science, and teaching myself software development.
The next ~three years would be spent exactly this way, to the very day I write this. There is zero substitution for hard work, and I intend
on continuing to use every moment of my remaining sentence to improve myself and my skills.&lt;&#x2F;p&gt;
&lt;p&gt;During the pandemic, staff were sympathetic to the residents here, who were unable to see loved ones, and unable to spend their time on the internet
when everything was shut down and we were locked in our rooms like they had. This brought about the internet being brought into a prison system,
for probably the first time in the country. Being technically inclined, led me the opportunity to work for the education department and I ended up
helping considerably in getting things working properly. And I still do.&lt;&#x2F;p&gt;
&lt;p&gt;After helping with the network for some time and implementing some software solutions for the DOC, when I asked for permission to seek remote
employment, they obliged. I was one of the first people in the country to to be allowed to be on &quot;remote work-release&quot; from a medium security prison.&lt;&#x2F;p&gt;
&lt;p&gt;I believe this highlights the fact that you cannot take opportunities that you are not given, and I would &lt;em&gt;never&lt;&#x2F;em&gt;
be in the position I am now: a completely changed man, working full-time from my cell, with a career doing what I
love not only programming, but also helping improve the system.(&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unlockedlabs.org&quot;&gt;details&lt;&#x2F;a&gt;); if this opportunity wasn&#x27;t given to me in
the form of a laptop and limited internet access. This is an incredibly rare situation, Maine is the &lt;em&gt;only&lt;&#x2F;em&gt; state in
the country where these particular opportunities exist at all (and for a limited number of residents, currently just
those enrolled in College, and there are many restrictions).&lt;&#x2F;p&gt;
&lt;p&gt;I am very grateful for the opportunity, but I recognize that this is very much the exception and not the rule, and the
success of the Maine model of corrections should highlight the absolutely embarrassing lack of opportunities in the rest
of the system, to do anything but become a bitter, broke criminal; deprived of not just your freedom, family, financial
security and reputation, but also of your self-identity as someone worth investing in changing. We need to do better as a
society, and understand that, yes, there are people in the system that deserve this kind of punishment, but a large majority
of our prison population are just regular people... non-violent drug offenders like myself. There are plenty more, like me,
that are capable of being responsible, productive, tax paying members of society if given the opportunity, but you cannot
expect anyone to change when you just lock them up in a cage with a bunch of other criminals where there is a subculture of
endless negativity.&lt;&#x2F;p&gt;
&lt;p&gt;If you are interested in helping support the education of incarcerated individuals, please consider donating to a company like the one I currently work for, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unlockedlabs.org&#x2F;&quot;&gt;Unlocked Labs&lt;&#x2F;a&gt; or similar non-profits like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;thelastmile.org&#x2F;&quot;&gt;The Last Mile&lt;&#x2F;a&gt; that are working to improve the system of mass-incarceration and provide opportunities for the incarcerated to learn and grow.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks for taking the time to read this...&lt;&#x2F;p&gt;
&lt;p&gt;-P&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;EDIT: Wow.. I definitely wasn&#x27;t expecting this to get to the front page of HN. In light of this, and some harsh, but undoubtedly fair comments that were made(as well as some completely ignorant ones). I would like to add some clarification on a few things.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I have been an opioid addict for over 10 years, and to this day prescribed suboxone, being treated for OUD as well as recently having been cured of HEP C from years of drug abuse. As an addict and someone that has seen this lifestyle, and drugs in particular claim the lives of countless friends (2 of them extremely close to me. RIP Mark Bochner, Scott Young.) I am &lt;strong&gt;absolutely&lt;&#x2F;strong&gt;, and forever will be ashamed of any participation I had in that lifestyle and for perpetuating the scourge of addiction. I would like to apologize publicly to anyone that has been affected by this, and there is no excuse for my actions, other than the same (terrible) one I give am forced to give for all of them. That I was young, ignorant, addicted, and I held absolutely no value for own life, nor lives of others. I am genuinely sorry and ashamed on a level that could never be properly communicated, and I understand that although I will have to live with that for the rest of my life, many others will not get that chance.&lt;&#x2F;p&gt;
&lt;p&gt;In the system, people are very open and accepting of their fate. Jokes are often made about how short someone was &#x27;on the street&#x27;, or bets will be placed how quickly someone will be back (always in months). Everyone speaks about release as if it is temporary, like a vacation from their accepted fate of prison or death. This is contagious, and when someone loses all value for their own life in acceptance of that fate, it creates a population of miserable, hopeless people with nothing to lose. As stated in the original post: I did not value my own life, nor did I believe I was capable of anything more than the life I had resided to.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Update 10&#x2F;03&#x2F;24: it&#x27;s been almost a year since I posted this.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;In May I was promoted to Senior Developer + tech lead for the product team, so it&#x27;s been very exciting leading development with a team of 6 going on 7 people now, and all of the other responsibilities that come along with it. I have had the chance to conduct technical interviews for two developer positions we filled, and I have spent the past few months teaching&#x2F;mentoring another resident in a different facility in Maine who I was put in contact with. I had heard he matched my level of discipline by putting in 14 hour days learning every single day. That has been the most rewarding thing I&#x27;ve done, because he put in a tremendous amount of work and we are now hiring him this week and I am fortunate enough to see and have directly contributed to the same life altering changes that have happened to me over the past few years.&lt;&#x2F;p&gt;
&lt;p&gt;I cannot recommend enough that devs volunteer some time teaching or mentoring, not only do you learn a ton yourself but it is really exciting seeing how efficiently you can teach someone else the things that you had to meticulously piece together yourself. Optimizing someone else&#x27;s learning path scratches the same automate&#x2F;optimize itch we devs get naturally, and the feeling that you are positively impacting someone&#x27;s life is a great feeling.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Update 06&#x2F;16&#x2F;2025:&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Update available on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;turso.tech&#x2F;blog&#x2F;working-on-databases-from-prison&quot;&gt;Turso&lt;&#x2F;a&gt;&#x27;s blog&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
