<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Pattern-Matching on</title><link>/tags/pattern-matching/</link><description>Recent content in Pattern-Matching on</description><generator>Hugo</generator><language>en</language><lastBuildDate>Thu, 08 Aug 2024 12:40:00 +0000</lastBuildDate><atom:link href="/tags/pattern-matching/index.xml" rel="self" type="application/rss+xml"/><item><title>Lesson 8: Refutable vs Irrefutable Patterns — Where they apply</title><link>/post/rust/rust-patterns-refutable/</link><pubDate>Thu, 08 Aug 2024 12:40:00 +0000</pubDate><guid>/post/rust/rust-patterns-refutable/</guid><description>&lt;p&gt;I remember the first time the Rust compiler told me &amp;ldquo;refutable pattern in local binding.&amp;rdquo; I stared at the error for five minutes, Googled &amp;ldquo;refutable pattern Rust,&amp;rdquo; read the explanation, and thought: &amp;ldquo;That&amp;rsquo;s&amp;hellip; actually a really good distinction that no other language makes explicit.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Every pattern in Rust is either refutable or irrefutable. Understanding which is which — and where each is allowed — clears up a whole class of confusing compiler errors.&lt;/p&gt;</description></item><item><title>Lesson 7: The Visitor Pattern via Enums — When trait objects won't cut it</title><link>/post/rust/rust-patterns-visitor/</link><pubDate>Mon, 05 Aug 2024 20:15:00 +0000</pubDate><guid>/post/rust/rust-patterns-visitor/</guid><description>&lt;p&gt;I spent a week once trying to make trait objects work for an AST walker. Every new operation meant a new trait, a new impl block for every node type, and a growing pile of boilerplate. When I rewrote the whole thing with an enum and match, the code shrank by 60% and got faster. Not every problem needs dynamic dispatch.&lt;/p&gt;
&lt;h2 id="the-problem-open-vs-closed-hierarchies"&gt;The Problem: Open vs. Closed Hierarchies&lt;/h2&gt;
&lt;p&gt;In object-oriented languages, the visitor pattern exists because class hierarchies are &amp;ldquo;open&amp;rdquo; — anyone can add new subclasses, so you can&amp;rsquo;t write a switch over all possible types. You need double dispatch through interfaces.&lt;/p&gt;</description></item><item><title>Lesson 6: State Machines with Enums — Compile-time guarantees</title><link>/post/rust/rust-patterns-state-machines/</link><pubDate>Fri, 02 Aug 2024 07:20:00 +0000</pubDate><guid>/post/rust/rust-patterns-state-machines/</guid><description>&lt;p&gt;Three years ago, I debugged a payment processing system where an order could go from &amp;ldquo;refunded&amp;rdquo; back to &amp;ldquo;shipped.&amp;rdquo; Nobody intended for that to happen. The state machine was implemented with a status string and a bunch of if/else checks scattered across eight files. One developer added a shortcut. Review missed it. Customers got refund emails followed by shipping confirmations.&lt;/p&gt;
&lt;p&gt;If the state machine had been in the type system, that shortcut wouldn&amp;rsquo;t have compiled.&lt;/p&gt;</description></item><item><title>Lesson 5: Enums Carrying Data — Modeling real domains</title><link>/post/rust/rust-patterns-enums-data/</link><pubDate>Tue, 30 Jul 2024 09:55:00 +0000</pubDate><guid>/post/rust/rust-patterns-enums-data/</guid><description>&lt;p&gt;The worst bug I ever shipped came from a &lt;code&gt;status&lt;/code&gt; field that was a string. It could be &amp;ldquo;active&amp;rdquo;, &amp;ldquo;Active&amp;rdquo;, &amp;ldquo;ACTIVE&amp;rdquo;, &amp;ldquo;active &amp;ldquo;, or — my personal favorite — &amp;ldquo;acitve&amp;rdquo;. Six months of data with a typo nobody caught because strings don&amp;rsquo;t have a compiler checking them.&lt;/p&gt;
&lt;p&gt;Rust enums would have made that bug impossible.&lt;/p&gt;
&lt;h2 id="the-problem-with-primitive-obsession"&gt;The Problem With Primitive Obsession&lt;/h2&gt;
&lt;p&gt;In most languages, developers reach for strings, integers, and booleans to represent domain concepts. A user&amp;rsquo;s role is a string. An order status is an integer. A payment method is&amp;hellip; also a string. This is called &amp;ldquo;primitive obsession&amp;rdquo; and it&amp;rsquo;s responsible for an entire category of bugs:&lt;/p&gt;</description></item><item><title>Lesson 4: Or Patterns, @ Bindings, and Rest Patterns — The full syntax</title><link>/post/rust/rust-patterns-or-at/</link><pubDate>Sat, 27 Jul 2024 14:10:00 +0000</pubDate><guid>/post/rust/rust-patterns-or-at/</guid><description>&lt;p&gt;I was reviewing a PR last year where someone had written twelve match arms for an enum — four groups of three variants that all did the same thing. Each group was identical code, copy-pasted three times. I left a one-line comment: &amp;ldquo;or patterns.&amp;rdquo; The whole match collapsed from 36 lines to 12.&lt;/p&gt;
&lt;p&gt;Most Rust developers learn the basics of &lt;code&gt;match&lt;/code&gt; early and never dig into the full pattern syntax. That&amp;rsquo;s a shame, because there are three features that eliminate a ton of redundancy: or patterns, &lt;code&gt;@&lt;/code&gt; bindings, and rest patterns.&lt;/p&gt;</description></item><item><title>Lesson 3: Match Guards and Bindings — Fine-grained control</title><link>/post/rust/rust-patterns-guards/</link><pubDate>Thu, 25 Jul 2024 08:30:00 +0000</pubDate><guid>/post/rust/rust-patterns-guards/</guid><description>&lt;p&gt;A few months back I was writing a rate limiter. The logic was simple: if the request is from an internal IP &lt;em&gt;and&lt;/em&gt; the rate is under the limit, allow it. If it&amp;rsquo;s external &lt;em&gt;and&lt;/em&gt; under a different limit, allow it. Otherwise, reject. I started with nested &lt;code&gt;if&lt;/code&gt; statements inside match arms and ended up with something that looked like a plate of spaghetti. Then I rewrote it with match guards and the whole function collapsed to six clean lines.&lt;/p&gt;</description></item><item><title>Lesson 2: Destructuring — Structs, tuples, enums, nested</title><link>/post/rust/rust-patterns-destructuring/</link><pubDate>Mon, 22 Jul 2024 16:45:00 +0000</pubDate><guid>/post/rust/rust-patterns-destructuring/</guid><description>&lt;p&gt;I used to write code like &lt;code&gt;point.x&lt;/code&gt;, &lt;code&gt;point.y&lt;/code&gt;, &lt;code&gt;point.z&lt;/code&gt; over and over in the same function. Three fields, three accesses, repeated twelve times. Then I learned destructuring and realized I&amp;rsquo;d been doing the equivalent of opening a package, looking at each item individually, and putting it back before looking at the next one.&lt;/p&gt;
&lt;p&gt;Destructuring is opening the package and grabbing everything at once.&lt;/p&gt;
&lt;h2 id="the-problem-with-field-by-field-access"&gt;The Problem With Field-by-Field Access&lt;/h2&gt;
&lt;p&gt;When you work with compound types — structs, tuples, enums with data — you constantly need to pull values out of them. In most languages, this means dot access or method calls, and you end up with verbose code that obscures the actual logic:&lt;/p&gt;</description></item><item><title>Lesson 1: match — Exhaustive by design</title><link>/post/rust/rust-patterns-match-exhaustive/</link><pubDate>Sat, 20 Jul 2024 11:23:00 +0000</pubDate><guid>/post/rust/rust-patterns-match-exhaustive/</guid><description>&lt;p&gt;I shipped a Python service once that had a &lt;code&gt;match&lt;/code&gt; statement handling four message types. Three months later, the team added a fifth type. Nobody updated the match. The default branch silently swallowed the new messages, and we lost two days of analytics data before anyone noticed.&lt;/p&gt;
&lt;p&gt;Rust&amp;rsquo;s &lt;code&gt;match&lt;/code&gt; wouldn&amp;rsquo;t have let that happen.&lt;/p&gt;
&lt;h2 id="the-problem-with-non-exhaustive-matching"&gt;The Problem With Non-Exhaustive Matching&lt;/h2&gt;
&lt;p&gt;Most languages treat pattern matching (or switch/case) as a convenience. You list the cases you care about, slap a default at the bottom, and move on. The problem is that code evolves. New variants get added, old assumptions break, and that default case quietly covers up bugs.&lt;/p&gt;</description></item></channel></rss>