This commit is contained in:
lavafroth
2025-11-03 02:52:24 +00:00
parent 4edbf1ab68
commit 1e6aec9d9e
31 changed files with 205 additions and 41 deletions

2
app.min.css vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.152.2"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=./header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=./about/ aria-label=about style=--url:url(./about.svg)></a><a href=./art/ aria-label=art style=--url:url(./art.svg)></a><a href=./index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=./pagefind/pagefind-ui.css rel=stylesheet><script src=./pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 4 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<!doctype html><html lang=en-us><head><meta name=generator content="Hugo 0.152.2"><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=./header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=./about/ aria-label=about style=--url:url(./about.svg)></a><a href=./art/ aria-label=art style=--url:url(./art.svg)></a><a href=./index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=./pagefind/pagefind-ui.css rel=stylesheet><script src=./pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 5 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<a href=https://lavafroth.is-a.dev/tags/decorators class=list-tag>Decorators</a>
<a href=https://lavafroth.is-a.dev/tags/rust class=list-tag>Rust</a>
<a href=https://lavafroth.is-a.dev/tags/algebraic-data-types class=list-tag>Algebraic Data Types</a>

View File

@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>lavafroth</title><link>https://lavafroth.is-a.dev/</link><description>Recent content on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like rust for its ergonomic features, University has forced me to use Python for the past couple of months, especially because of the hype for machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Fortunately, since Python 3.8, creating structs has been a breeze using the dataclass decorator. There&amp;rsquo;s even support for structural match expressions, like in rust, in recent versions of &lt;a href="https://peps.python.org/pep-0636/"&gt;Python&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>note skta4v7n8h8</title><link>https://lavafroth.is-a.dev/skta4v7n8h8/</link><pubDate>Fri, 31 Oct 2025 20:24:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/skta4v7n8h8/</guid><description>&lt;h1 id="grpa-1"&gt;GrPA 1&lt;/h1&gt;
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>lavafroth</title><link>https://lavafroth.is-a.dev/</link><description>Recent content on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like Rust for its ergonomic features, university has forced me to
use Python for the past couple of months, especially because of the hype for
machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable
data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Although Python has the answer to creating structs as
&lt;a href="https://peps.python.org/pep-0557/"&gt;dataclasses&lt;/a&gt;, including support for
&lt;a href="https://peps.python.org/pep-0636/"&gt;structural match expressions&lt;/a&gt; in recent
versions, most tutorials will suggest &lt;code&gt;Union&lt;/code&gt; types as the equivalent to Rust&amp;rsquo;s
enums.&lt;/p&gt;</description></item><item><title>note skta4v7n8h8</title><link>https://lavafroth.is-a.dev/skta4v7n8h8/</link><pubDate>Fri, 31 Oct 2025 20:24:35 +0530</pubDate><guid>https://lavafroth.is-a.dev/skta4v7n8h8/</guid><description>&lt;h1 id="grpa-1"&gt;GrPA 1&lt;/h1&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;def&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;swap&lt;/span&gt;(arr, i, j):
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; arr[i], arr[j] &lt;span style="color:#f92672"&gt;=&lt;/span&gt; arr[j], arr[i]
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1 +1 @@
{"version":"1.0.3","languages":{"en-us":{"hash":"en-us_6a23f48a599dc","wasm":"en-us","page_count":58}}}
{"version":"1.0.3","languages":{"en-us":{"hash":"en-us_f3d6bd8299974","wasm":"en-us","page_count":58}}}

Binary file not shown.

View File

@@ -1,6 +1,21 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Algebraic Python Enums - lavafroth</title><meta name=description content='As much as I like rust for its ergonomic features, University has forced me to use Python for the past couple of months, especially because of the hype for machine learning and data science.
One of the biggest things that I missed from the rust experience was enumerable data types whose variants can wrap around different datatypes.
Fortunately, since Python 3.8, creating structs has been a breeze using the dataclass decorator. There&rsquo;s even support for structural match expressions, like in rust, in recent versions of Python.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Nov 2, 2025 | 4 minutes read</time></p><h1 data-pagefind-meta=title>Algebraic Python Enums</h1></hgroup><section class=post-content data-pagefind-body><p>As much as I like rust for its ergonomic features, University has forced me to use Python for the past couple of months, especially because of the hype for machine learning and data science.</p><p>One of the biggest things that I missed from the rust experience was enumerable data types whose variants can wrap around different datatypes.</p><p>Fortunately, since Python 3.8, creating structs has been a breeze using the dataclass decorator. There&rsquo;s even support for structural match expressions, like in rust, in recent versions of <a href=https://peps.python.org/pep-0636/>Python</a>.</p><p>To that end, creating the equivalent to Rust&rsquo;s enum types involves Python union types.</p><h2 id=first-draft>First draft</h2><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># glass_enum.py</span>
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Algebraic Python Enums - lavafroth</title><meta name=description content='As much as I like Rust for its ergonomic features, university has forced me to
use Python for the past couple of months, especially because of the hype for
machine learning and data science.
One of the biggest things that I missed from the rust experience was enumerable
data types whose variants can wrap around different datatypes.
Although Python has the answer to creating structs as
dataclasses, including support for
structural match expressions in recent
versions, most tutorials will suggest Union types as the equivalent to Rust&rsquo;s
enums.'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><hgroup data-pagefind-body><p data-pagefind-ignore><time>Nov 2, 2025 | 5 minutes read</time></p><h1 data-pagefind-meta=title>Algebraic Python Enums</h1></hgroup><section class=post-content data-pagefind-body><p>As much as I like Rust for its ergonomic features, university has forced me to
use Python for the past couple of months, especially because of the hype for
machine learning and data science.</p><p>One of the biggest things that I missed from the rust experience was enumerable
data types whose variants can wrap around different datatypes.</p><p>Although Python has the answer to creating structs as
<a href=https://peps.python.org/pep-0557/>dataclasses</a>, including support for
<a href=https://peps.python.org/pep-0636/>structural match expressions</a> in recent
versions, most tutorials will suggest <code>Union</code> types as the equivalent to Rust&rsquo;s
enums.</p><blockquote><p>I highly encourage you to try out the code snippets and follow along with this article.
Use the collapse explanation button to copy multiple code blocks in one go.</p></blockquote><h2 id=naive-draft>Naive draft</h2><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># glass_enum.py</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
@@ -19,8 +34,63 @@ Fortunately, since Python 3.8, creating structs has been a breeze using the data
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>&#34;Whoops, looks like you&#39;ve finished your drink!&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Full(drink):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;Ah a </span><span style=color:#e6db74>{</span>drink<span style=color:#e6db74>}</span><span style=color:#e6db74>, what a fine taste!&#34;</span>
</span></span></code></pre></div><h2 id=pitfalls>Pitfalls</h2><h3 id=no-direct-variant-access>No direct variant access</h3><p>Since there is no namespacing, we also can&rsquo;t instantiate variants under the <code>Glass</code> namespace. The following code does not work.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#34;Dr. Pepper&#34;</span>)
</span></span></code></pre></div><p>This can be partially solved by putting the entire enumerable type inside a module.
</span></span></code></pre></div><p>For example</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#39;Dr. Pepper&#39;</span>)
</span></span><span style=display:flex><span>print(report_drink(dr_pepper))
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#75715e># glass_enum.py</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Empty</span>:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pass</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> drink: str
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>Glass <span style=color:#f92672>=</span> Empty <span style=color:#f92672>|</span> Full
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>report_drink</span>(glass: Glass) <span style=color:#f92672>-&gt;</span> str:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> glass:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Empty():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>&#34;Whoops, looks like you&#39;ve finished your drink!&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Full(drink):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;Ah a </span><span style=color:#e6db74>{</span>drink<span style=color:#e6db74>}</span><span style=color:#e6db74>, what a fine taste!&#34;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#39;Dr. Pepper&#39;</span>)
</span></span><span style=display:flex><span>print(report_drink(dr_pepper))
</span></span></code></pre></div><div class=container></div></div><p>Will output</p><pre tabindex=0><code>Ah a Dr. Pepper, what a fine taste!
</code></pre><h2 id=pitfalls>Pitfalls</h2><h3 id=no-direct-variant-access>No direct variant access</h3><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><p>What if we had another <code>Union</code> with same variant names in the same file?</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> gold: int
</span></span><span style=display:flex><span> gems: int
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Empty</span>:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pass</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>Inventory <span style=color:#f92672>=</span> Full <span style=color:#f92672>|</span> Empty
</span></span><span style=display:flex><span>player_inventory <span style=color:#f92672>=</span> Full(<span style=color:#ae81ff>500</span>, <span style=color:#ae81ff>50</span>)
</span></span></code></pre></div><p>Now we try to instantiate a <code>Glass</code> <code>Full</code> of <code>lemonade</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>lemonade <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#34;lemonade&#34;</span>)
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> gold: int
</span></span><span style=display:flex><span> gems: int
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Empty</span>:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pass</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>Inventory <span style=color:#f92672>=</span> Full <span style=color:#f92672>|</span> Empty
</span></span><span style=display:flex><span>player_inventory <span style=color:#f92672>=</span> Full(<span style=color:#ae81ff>500</span>, <span style=color:#ae81ff>50</span>)
</span></span><span style=display:flex><span>lemonade <span style=color:#f92672>=</span> Full(<span style=color:#e6db74>&#34;lemonade&#34;</span>)
</span></span></code></pre></div><div class=container></div></div><p>Python will error out since <code>Full</code> now refers to the new variant of the
union type <code>Inventory</code>.</p><pre tabindex=0><code>Traceback (most recent call last):
File &#34;&lt;python-input-11&gt;&#34;, line 1, in &lt;module&gt;
lemonade = Full(&#34;lemonade&#34;)
TypeError: Full.__init__() missing 1 required positional argument: &#39;gems&#39;
</code></pre><p>We can&rsquo;t instantiate variants as members of the <code>Glass</code> namespace. The following code does not work.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>dr_pepper <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#34;Dr. Pepper&#34;</span>)
</span></span></code></pre></div><p>This can be partially solved by keeping just the <code>Glass</code> type inside a module.
Here we have saved the file as <code>glass_enum.py</code>. From a different module we can
access the variants as <code>glass_enum.Empty</code> and <code>glass_enum.Full</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-py data-lang=py><span style=display:flex><span><span style=color:#75715e># main.py</span>
</span></span><span style=display:flex><span><span style=color:#f92672>import</span> glass_enum
@@ -30,12 +100,14 @@ access the variants as <code>glass_enum.Empty</code> and <code>glass_enum.Full</
</span></span></code></pre></div><p>Now any function outside the module has to ingest a rather confusing argument of type <code>glass_enum.Glass</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>refill</span>(glass: glass_enum<span style=color:#f92672>.</span>Glass) <span style=color:#f92672>-&gt;</span> glass_enum<span style=color:#f92672>.</span>Glass:
</span></span><span style=display:flex><span> <span style=color:#75715e># ...</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> glass
</span></span></code></pre></div><p>Since using a module namespace only causes more confusion, we will discard this idea.</p><h3 id=no-methods-on-the-enum-itself>No methods on the enum itself</h3><p>With no namespaceing, methods cannot be defined on the <code>Union</code> of the different variants.</p><p>In the case of our concrete example, we can&rsquo;t add methods to the <code>Glass</code> type.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>refill</span>(glass: Glass) <span style=color:#f92672>-&gt;</span> Glass:
</span></span></code></pre></div><p>Since module namespacing only causes more confusion, we will discard this idea.</p><h3 id=no-methods-on-the-enum-itself>No methods on the enum itself</h3><p>Python also disallows methods from being defined on <code>Union</code> types.
In the case of our concrete example, we can&rsquo;t add methods to the <code>Glass</code> type.</p><p>The following code uses a hypothetical <code>is_empty()</code> method on the <code>Glass</code> union
type which is not allowed. Hence the code won&rsquo;t run.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>refill</span>(glass: Glass) <span style=color:#f92672>-&gt;</span> Glass:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> glass<span style=color:#f92672>.</span>is_empty(): <span style=color:#75715e># can&#39;t implement on type `Glass` directly</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> Full(<span style=color:#e6db74>&#39;water&#39;</span>)
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> glass
</span></span></code></pre></div><p>Even if we use module level namespacing, it&rsquo;s simply not possible to define any method on a <code>Union</code> type in Python.</p><p>To define a method like <code>is_empty()</code>, it must be implemented on both the classes <code>Full</code> and <code>Empty</code>. This can get
tedious if there are 3 or more variants.</p><h2 id=python-is-a-sneaky-language>Python is a sneaky language</h2><p>Last week I discovered that Python allows creating nested classes to keep things organized.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span></code></pre></div><p>To define a method like <code>is_empty()</code>, it must be implemented on both the classes
<code>Full</code> and <code>Empty</code>. This gets tedious for 3 or more variants.</p><h2 id=python-is-a-sneaky-language>Python is a sneaky language</h2><p>Last week I discovered that Python allows creating nested classes to keep things organized.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Glass</span>:
</span></span><span style=display:flex><span> <span style=color:#a6e22e>@dataclass</span>
@@ -46,7 +118,7 @@ tedious if there are 3 or more variants.</p><h2 id=python-is-a-sneaky-language>P
</span></span><span style=display:flex><span> <span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> drink: str
</span></span></code></pre></div><p>Python will happily run the above code and we can access the &ldquo;variants&rdquo; under the <code>Glass</code> namespace.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>lemonade <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#39;lemonade&#39;</span>)
</span></span></code></pre></div><p>If only we could register the variants as the <code>Glass</code> type itself and inherit all its methods.</p><h3 id=redecorate>Redecorate</h3><p>We can define a decorator that takes all of the nested dataclasses and makes them inherit the outer class.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> inspect
</span></span></code></pre></div><p>If only we could register the variants as the <code>Glass</code> type itself and inherit all its methods.</p><h3 id=redecorate>Redecorate</h3><p>We can define a decorator that takes all of the nested dataclasses and makes them inherit the outer class.</p><div class=collapsable-explanation><div class=container><label><input type=checkbox></label></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> inspect
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>AlgebraicEnum</span>(cls):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> subclass_name, subclass <span style=color:#f92672>in</span> inspect<span style=color:#f92672>.</span>getmembers(cls, predicate<span style=color:#f92672>=</span>inspect<span style=color:#f92672>.</span>isclass):
@@ -54,7 +126,8 @@ tedious if there are 3 or more variants.</p><h2 id=python-is-a-sneaky-language>P
</span></span><span style=display:flex><span> setattr(cls, subclass_name, type(subclass_name, (cls, subclass), {}))
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> cls
</span></span></code></pre></div><p>That&rsquo;s all there is to the magic! Now we can simply add this decorator above the previous class declaration
</span></span></code></pre></div><p>The inheritance means all methods of the outer class are available on the nested
classes <em>and</em> any object of a nested class <code>isinstance</code> of the outer class.</p><p>That&rsquo;s all there is to the magic! Now we can simply add this decorator above the previous class declaration
and the variants like <code>Glass.Empty</code> and <code>Glass.Full</code> would be of the type <code>Glass</code>.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#a6e22e>@AlgebraicEnum</span>
@@ -67,22 +140,71 @@ and the variants like <code>Glass.Empty</code> and <code>Glass.Full</code> would
</span></span><span style=display:flex><span> <span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> drink: str
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>report_drink</span>(self) <span style=color:#f92672>-&gt;</span> str:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>report_drink</span>(self: <span style=color:#e6db74>&#39;Glass&#39;</span>) <span style=color:#f92672>-&gt;</span> str:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> self:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Glass<span style=color:#f92672>.</span>Empty():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>&#34;Whoops, looks like you&#39;ve finished your drink!&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Glass<span style=color:#f92672>.</span>Full(drink):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;Ah a </span><span style=color:#e6db74>{</span>drink<span style=color:#e6db74>}</span><span style=color:#e6db74>, what a fine taste!&#34;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>is_empty</span>(self) <span style=color:#f92672>-&gt;</span> str:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>is_empty</span>(self: <span style=color:#e6db74>&#39;Glass&#39;</span>) <span style=color:#f92672>-&gt;</span> bool:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> self:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Glass<span style=color:#f92672>.</span>Empty():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>True</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>False</span>
</span></span></code></pre></div><p>As a bonus, the variants will also inherit any methods defined on the <code>Glass</code> type.</p><p>Note how the <code>report_drink</code> method accepts a <code>self</code> of type <code>Glass</code> and the match arms
compare it with <code>Glass.Empty</code> and <code>Glass.Full</code>.</p><p>These methods get automatically called via the method resolution order chain due to the inheritance.</p><h2 id=closing-thoughts>Closing thoughts</h2><p>Those 6 lines are the bare minimum of what you can do right now to have well organized and namespaced algebraic enums in Python
which are somewhat comparable to those in Rust. These enums also play nicely with static type checkers
and <em>goto-definitions</em> will also lead you to the correct class defining a variant or the enum itself.</p><p>I have packaged this decorator with a couple more typing restrictions into a library at <a href=https://github.com/lavafroth/ape>github:lavafroth/ape</a>.</p><p>I hope you enjoyed this foray into contorting Python.</p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
compare it with <code>Glass.Empty</code> and <code>Glass.Full</code>.</p><p>These methods get automatically called via the method resolution order chain due to the inheritance.</p><p>The following code runs just fine.</p><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span>diet_coke <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#39;diet coke&#39;</span>)
</span></span><span style=display:flex><span>empty <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Empty()
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>print(diet_coke<span style=color:#f92672>.</span>report_drink())
</span></span><span style=display:flex><span>print(empty<span style=color:#f92672>.</span>is_empty())
</span></span></code></pre></div><div class=highlight><pre tabindex=0 style=color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4><code class=language-python data-lang=python><span style=display:flex><span><span style=color:#f92672>import</span> inspect
</span></span><span style=display:flex><span><span style=color:#f92672>from</span> dataclasses <span style=color:#f92672>import</span> dataclass
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>def</span> <span style=color:#a6e22e>AlgebraicEnum</span>(cls):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>for</span> subclass_name, subclass <span style=color:#f92672>in</span> inspect<span style=color:#f92672>.</span>getmembers(cls, predicate<span style=color:#f92672>=</span>inspect<span style=color:#f92672>.</span>isclass):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> subclass_name <span style=color:#f92672>!=</span> <span style=color:#e6db74>&#34;__class__&#34;</span>:
</span></span><span style=display:flex><span> setattr(cls, subclass_name, type(subclass_name, (cls, subclass), {}))
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> cls
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#a6e22e>@AlgebraicEnum</span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Glass</span>:
</span></span><span style=display:flex><span> <span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Empty</span>:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>pass</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#a6e22e>@dataclass</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>class</span> <span style=color:#a6e22e>Full</span>:
</span></span><span style=display:flex><span> drink: str
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>report_drink</span>(self: <span style=color:#e6db74>&#39;Glass&#39;</span>) <span style=color:#f92672>-&gt;</span> str:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> self:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Glass<span style=color:#f92672>.</span>Empty():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>&#34;Whoops, looks like you&#39;ve finished your drink!&#34;</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Glass<span style=color:#f92672>.</span>Full(drink):
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#e6db74>f</span><span style=color:#e6db74>&#34;Ah a </span><span style=color:#e6db74>{</span>drink<span style=color:#e6db74>}</span><span style=color:#e6db74>, what a fine taste!&#34;</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>def</span> <span style=color:#a6e22e>is_empty</span>(self: <span style=color:#e6db74>&#39;Glass&#39;</span>) <span style=color:#f92672>-&gt;</span> bool:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> self:
</span></span><span style=display:flex><span> <span style=color:#66d9ef>case</span> Glass<span style=color:#f92672>.</span>Empty():
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>True</span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>return</span> <span style=color:#66d9ef>False</span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>diet_coke <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Full(<span style=color:#e6db74>&#39;diet coke&#39;</span>)
</span></span><span style=display:flex><span>empty <span style=color:#f92672>=</span> Glass<span style=color:#f92672>.</span>Empty()
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span>print(diet_coke<span style=color:#f92672>.</span>report_drink())
</span></span><span style=display:flex><span>print(empty<span style=color:#f92672>.</span>is_empty())
</span></span></code></pre></div><div class=container></div></div><pre tabindex=0><code>Ah a diet coke, what a fine taste!
True
</code></pre><h2 id=closing-thoughts>Closing thoughts</h2><p>Those 6 lines are the bare minimum to get well organized and namespaced
algebraic enums in Python that are somewhat comparable to the ones in Rust. These
enums also play nicely with static type checkers, <em>goto-definitions</em> will
lead you to the correct class definition.</p><p>I have packaged this decorator with a couple more typing restrictions into a library at <a href=https://github.com/lavafroth/ape>github:lavafroth/ape</a>.</p><p>I hope you enjoyed this foray into contorting Python.</p></section><footer class=post-tags data-pagefind-meta=tags><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<a href=https://lavafroth.is-a.dev/tags/decorators class=list-tag>Decorators</a>
<a href=https://lavafroth.is-a.dev/tags/rust class=list-tag>Rust</a>
<a href=https://lavafroth.is-a.dev/tags/algebraic-data-types class=list-tag>Algebraic Data Types</a></footer><nav data-post><br><a href=https://lavafroth.is-a.dev/post/nixos-notes-to-self/><span>NixOS Notes to Self</span><span></span></a></nav></main><footer class=footer><p>&copy; 2025 <a href=https://lavafroth.is-a.dev/>lavafroth</a></p><p><a href=https://github.com/lavafroth/lavafroth.github.io/issues/new/choose>Report an issue</a></p><p><a href=https://github.com/lavafroth/lavafroth.github.io/discussions/>Discuss</a></p><p><a href=https://lavafroth.is-a.dev/privacy>Privacy</a></p><p><a href=https://creativecommons.org/licenses/by-sa/4.0/legalcode>License</a></p></footer></body></html>

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Posts - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/post/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../pagefind/pagefind-ui.css rel=stylesheet><script src=../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 4 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Posts - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/post/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../pagefind/pagefind-ui.css rel=stylesheet><script src=../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 5 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<a href=https://lavafroth.is-a.dev/tags/decorators class=list-tag>Decorators</a>
<a href=https://lavafroth.is-a.dev/tags/rust class=list-tag>Rust</a>
<a href=https://lavafroth.is-a.dev/tags/algebraic-data-types class=list-tag>Algebraic Data Types</a>

View File

@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on lavafroth</title><link>https://lavafroth.is-a.dev/post/</link><description>Recent content in Posts on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/post/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like rust for its ergonomic features, University has forced me to use Python for the past couple of months, especially because of the hype for machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Fortunately, since Python 3.8, creating structs has been a breeze using the dataclass decorator. There&amp;rsquo;s even support for structural match expressions, like in rust, in recent versions of &lt;a href="https://peps.python.org/pep-0636/"&gt;Python&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>NixOS Notes to Self</title><link>https://lavafroth.is-a.dev/post/nixos-notes-to-self/</link><pubDate>Sun, 14 Sep 2025 18:31:52 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/nixos-notes-to-self/</guid><description>&lt;p&gt;A dedicated post collecting solutions to minor NixOS headaches.&lt;/p&gt;
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on lavafroth</title><link>https://lavafroth.is-a.dev/post/</link><description>Recent content in Posts on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/post/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like Rust for its ergonomic features, university has forced me to
use Python for the past couple of months, especially because of the hype for
machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable
data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Although Python has the answer to creating structs as
&lt;a href="https://peps.python.org/pep-0557/"&gt;dataclasses&lt;/a&gt;, including support for
&lt;a href="https://peps.python.org/pep-0636/"&gt;structural match expressions&lt;/a&gt; in recent
versions, most tutorials will suggest &lt;code&gt;Union&lt;/code&gt; types as the equivalent to Rust&amp;rsquo;s
enums.&lt;/p&gt;</description></item><item><title>NixOS Notes to Self</title><link>https://lavafroth.is-a.dev/post/nixos-notes-to-self/</link><pubDate>Sun, 14 Sep 2025 18:31:52 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/nixos-notes-to-self/</guid><description>&lt;p&gt;A dedicated post collecting solutions to minor NixOS headaches.&lt;/p&gt;
&lt;h2 id="nixos-rebuild-shows-no-network-activity"&gt;&lt;code&gt;nixos-rebuild&lt;/code&gt; shows no network activity&lt;/h2&gt;
&lt;p&gt;On rare occasions, a system rebuild will get stuck while downloading a package from a source.
No network activity, no timeout, no writes to the nix store.&lt;/p&gt;

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Algebraic Data Types - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/algebraic-data-types/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 4 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Algebraic Data Types - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/algebraic-data-types/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 5 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<a href=https://lavafroth.is-a.dev/tags/decorators class=list-tag>Decorators</a>
<a href=https://lavafroth.is-a.dev/tags/rust class=list-tag>Rust</a>
<a href=https://lavafroth.is-a.dev/tags/algebraic-data-types class=list-tag>Algebraic Data Types</a>

View File

@@ -1,3 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Algebraic Data Types on lavafroth</title><link>https://lavafroth.is-a.dev/tags/algebraic-data-types/</link><description>Recent content in Algebraic Data Types on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/algebraic-data-types/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like rust for its ergonomic features, University has forced me to use Python for the past couple of months, especially because of the hype for machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Fortunately, since Python 3.8, creating structs has been a breeze using the dataclass decorator. There&amp;rsquo;s even support for structural match expressions, like in rust, in recent versions of &lt;a href="https://peps.python.org/pep-0636/"&gt;Python&lt;/a&gt;.&lt;/p&gt;</description></item></channel></rss>
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Algebraic Data Types on lavafroth</title><link>https://lavafroth.is-a.dev/tags/algebraic-data-types/</link><description>Recent content in Algebraic Data Types on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/algebraic-data-types/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like Rust for its ergonomic features, university has forced me to
use Python for the past couple of months, especially because of the hype for
machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable
data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Although Python has the answer to creating structs as
&lt;a href="https://peps.python.org/pep-0557/"&gt;dataclasses&lt;/a&gt;, including support for
&lt;a href="https://peps.python.org/pep-0636/"&gt;structural match expressions&lt;/a&gt; in recent
versions, most tutorials will suggest &lt;code&gt;Union&lt;/code&gt; types as the equivalent to Rust&amp;rsquo;s
enums.&lt;/p&gt;</description></item></channel></rss>

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Decorators - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/decorators/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 4 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Decorators - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/decorators/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 5 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<a href=https://lavafroth.is-a.dev/tags/decorators class=list-tag>Decorators</a>
<a href=https://lavafroth.is-a.dev/tags/rust class=list-tag>Rust</a>
<a href=https://lavafroth.is-a.dev/tags/algebraic-data-types class=list-tag>Algebraic Data Types</a>

View File

@@ -1,3 +1,10 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Decorators on lavafroth</title><link>https://lavafroth.is-a.dev/tags/decorators/</link><description>Recent content in Decorators on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/decorators/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like rust for its ergonomic features, University has forced me to use Python for the past couple of months, especially because of the hype for machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Fortunately, since Python 3.8, creating structs has been a breeze using the dataclass decorator. There&amp;rsquo;s even support for structural match expressions, like in rust, in recent versions of &lt;a href="https://peps.python.org/pep-0636/"&gt;Python&lt;/a&gt;.&lt;/p&gt;</description></item></channel></rss>
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Decorators on lavafroth</title><link>https://lavafroth.is-a.dev/tags/decorators/</link><description>Recent content in Decorators on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/decorators/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like Rust for its ergonomic features, university has forced me to
use Python for the past couple of months, especially because of the hype for
machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable
data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Although Python has the answer to creating structs as
&lt;a href="https://peps.python.org/pep-0557/"&gt;dataclasses&lt;/a&gt;, including support for
&lt;a href="https://peps.python.org/pep-0636/"&gt;structural match expressions&lt;/a&gt; in recent
versions, most tutorials will suggest &lt;code&gt;Union&lt;/code&gt; types as the equivalent to Rust&amp;rsquo;s
enums.&lt;/p&gt;</description></item></channel></rss>

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Python - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/python/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 4 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Python - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/python/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 5 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<a href=https://lavafroth.is-a.dev/tags/decorators class=list-tag>Decorators</a>
<a href=https://lavafroth.is-a.dev/tags/rust class=list-tag>Rust</a>
<a href=https://lavafroth.is-a.dev/tags/algebraic-data-types class=list-tag>Algebraic Data Types</a>

View File

@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Python on lavafroth</title><link>https://lavafroth.is-a.dev/tags/python/</link><description>Recent content in Python on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like rust for its ergonomic features, University has forced me to use Python for the past couple of months, especially because of the hype for machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Fortunately, since Python 3.8, creating structs has been a breeze using the dataclass decorator. There&amp;rsquo;s even support for structural match expressions, like in rust, in recent versions of &lt;a href="https://peps.python.org/pep-0636/"&gt;Python&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>PicoCTF SansAlpha Writeup</title><link>https://lavafroth.is-a.dev/post/picoctf-sansalpha-writeup/</link><pubDate>Sun, 05 Jan 2025 11:55:52 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-sansalpha-writeup/</guid><description>&lt;p&gt;Hey everyone, since 2024 hasn&amp;rsquo;t seen a lot of posts on this blog, I plan to
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Python on lavafroth</title><link>https://lavafroth.is-a.dev/tags/python/</link><description>Recent content in Python on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like Rust for its ergonomic features, university has forced me to
use Python for the past couple of months, especially because of the hype for
machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable
data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Although Python has the answer to creating structs as
&lt;a href="https://peps.python.org/pep-0557/"&gt;dataclasses&lt;/a&gt;, including support for
&lt;a href="https://peps.python.org/pep-0636/"&gt;structural match expressions&lt;/a&gt; in recent
versions, most tutorials will suggest &lt;code&gt;Union&lt;/code&gt; types as the equivalent to Rust&amp;rsquo;s
enums.&lt;/p&gt;</description></item><item><title>PicoCTF SansAlpha Writeup</title><link>https://lavafroth.is-a.dev/post/picoctf-sansalpha-writeup/</link><pubDate>Sun, 05 Jan 2025 11:55:52 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/picoctf-sansalpha-writeup/</guid><description>&lt;p&gt;Hey everyone, since 2024 hasn&amp;rsquo;t seen a lot of posts on this blog, I plan to
start this year off by going back to the roots.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be focusing on posting more CTF writeups again! Today&amp;rsquo;s challenge is
&lt;em&gt;SansAlpha&lt;/em&gt; from PicoCTF. The challenge description states&lt;/p&gt;

View File

@@ -1,4 +1,4 @@
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Rust - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/rust/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 4 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<!doctype html><html lang=en-us><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1,shrink-to-fit=no"><title>Rust - lavafroth</title><meta name=description content='smol creator'><meta name=author content><link rel="preload stylesheet" as=style href=https://lavafroth.is-a.dev/app.min.css><link rel=preload as=image href=../../header.svg><link as=font href=https://lavafroth.is-a.dev/latinmodern-math.otf><link rel=preload as=image href=https://lavafroth.is-a.dev/github.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/about.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/art.svg><link rel=preload as=image href=https://lavafroth.is-a.dev/rss.svg><link rel=icon href=https://lavafroth.is-a.dev/favicon.png><link rel=blog-icon href=https://lavafroth.is-a.dev/icon.png><link rel=alternate type=application/rss+xml href=https://lavafroth.is-a.dev/tags/rust/index.xml title=lavafroth></head><body><header><a class=site-name href=https://lavafroth.is-a.dev/><svg viewBox="0 0 8790 2080"><path d="M80 1935V465h216v1270h286v2e2zm853 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm1025 528L2014 465h210l108 868 8 142h12l8-142 108-868h210l-224 1470zm813 0 222-1470h264l222 1470h-210l-40-3e2h-208l-40 3e2zm280-528h148l-62-494-6-78h-12l-6 78zm851 528V465h514v222h-298v386h2e2v222h-2e2v640zm910 0V465h216q194 0 286 108 92 107 92 316 0 124-43 215-44 90-106 132l147 699h-216l-122-620h-38v620zm216-820q60 0 95-26 35-27 50-76t15-116q0-105-34-161-35-57-126-57zm1084 836q-90 0-154-42-65-42-99-114-35-72-35-162V767q0-91 35-162 34-72 99-114 64-42 154-42t155 42q64 42 99 114 34 72 34 162v866q0 90-34 162-35 72-99 114-65 42-155 42zm0-210q40 0 56-33 16-34 16-75V767q0-41-17-74-17-34-55-34-37 0-54 34-18 33-18 74v866q0 41 17 75 17 33 55 33zm890 194V687h-204V465h624v222h-204v1248zm828 0V465h216v608h168V465h216v1470h-216v-640h-168v640z"/></svg></a><nav><a style=--url:url(./github.svg) href=https://github.com/lavafroth aria-label=github target=_blank></a><a href=../../about/ aria-label=about style=--url:url(./about.svg)></a><a href=../../art/ aria-label=art style=--url:url(./art.svg)></a><a href=../../index.xml aria-label=rss style=--url:url(./rss.svg)></a><nav></header><main><link href=../../pagefind/pagefind-ui.css rel=stylesheet><script src=../../pagefind/pagefind-ui.js type=text/javascript></script><search></search><section class=post-content></section><article><a aria-label="Algebraic Python Enums" href=https://lavafroth.is-a.dev/post/algebraic-python-enums/><h2>Algebraic Python Enums</h2></a><time>Nov 2, 2025 | 5 minutes read</time><br><a href=https://lavafroth.is-a.dev/tags/python class=list-tag>Python</a>
<a href=https://lavafroth.is-a.dev/tags/decorators class=list-tag>Decorators</a>
<a href=https://lavafroth.is-a.dev/tags/rust class=list-tag>Rust</a>
<a href=https://lavafroth.is-a.dev/tags/algebraic-data-types class=list-tag>Algebraic Data Types</a>

View File

@@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rust on lavafroth</title><link>https://lavafroth.is-a.dev/tags/rust/</link><description>Recent content in Rust on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/rust/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like rust for its ergonomic features, University has forced me to use Python for the past couple of months, especially because of the hype for machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Fortunately, since Python 3.8, creating structs has been a breeze using the dataclass decorator. There&amp;rsquo;s even support for structural match expressions, like in rust, in recent versions of &lt;a href="https://peps.python.org/pep-0636/"&gt;Python&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Wrapping up GSoC 2024</title><link>https://lavafroth.is-a.dev/post/the-gsoc-grand-finale/</link><pubDate>Sat, 24 Aug 2024 10:28:50 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/the-gsoc-grand-finale/</guid><description>&lt;h1 id="overview"&gt;Overview&lt;/h1&gt;
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rust on lavafroth</title><link>https://lavafroth.is-a.dev/tags/rust/</link><description>Recent content in Rust on lavafroth</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sun, 02 Nov 2025 19:08:46 +0530</lastBuildDate><atom:link href="https://lavafroth.is-a.dev/tags/rust/index.xml" rel="self" type="application/rss+xml"/><item><title>Algebraic Python Enums</title><link>https://lavafroth.is-a.dev/post/algebraic-python-enums/</link><pubDate>Sun, 02 Nov 2025 19:08:46 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/algebraic-python-enums/</guid><description>&lt;p&gt;As much as I like Rust for its ergonomic features, university has forced me to
use Python for the past couple of months, especially because of the hype for
machine learning and data science.&lt;/p&gt;
&lt;p&gt;One of the biggest things that I missed from the rust experience was enumerable
data types whose variants can wrap around different datatypes.&lt;/p&gt;
&lt;p&gt;Although Python has the answer to creating structs as
&lt;a href="https://peps.python.org/pep-0557/"&gt;dataclasses&lt;/a&gt;, including support for
&lt;a href="https://peps.python.org/pep-0636/"&gt;structural match expressions&lt;/a&gt; in recent
versions, most tutorials will suggest &lt;code&gt;Union&lt;/code&gt; types as the equivalent to Rust&amp;rsquo;s
enums.&lt;/p&gt;</description></item><item><title>Wrapping up GSoC 2024</title><link>https://lavafroth.is-a.dev/post/the-gsoc-grand-finale/</link><pubDate>Sat, 24 Aug 2024 10:28:50 +0530</pubDate><guid>https://lavafroth.is-a.dev/post/the-gsoc-grand-finale/</guid><description>&lt;h1 id="overview"&gt;Overview&lt;/h1&gt;
&lt;p&gt;Hello and welcome to the final GSoC post for 2024! My task was to formalize the SWHKD parser using context-free EBNF notation. This post is to serve as a birdseye view of what
I have developed over this summer.&lt;/p&gt;
&lt;h1 id="report"&gt;Report&lt;/h1&gt;