This commit is contained in:
Nilstrieb 2023-03-17 16:05:29 +00:00
parent 11964435c0
commit c457ac16c5
14 changed files with 807 additions and 10 deletions

View file

@ -1,4 +1,6 @@
<!doctype html><html lang=en><head><meta name=generator content="Hugo 0.111.3"><title>nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="nilstriebs blog"><meta property="og:description" content><meta property="og:url" content="/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=posts><div class="post on-list"><h1 class=post-title><a href=/posts/box-is-a-unique-type/>Box Is a Unique Type</a></h1><div class=post-meta><span class=post-date>2022-07-23</span> <!doctype html><html lang=en><head><meta name=generator content="Hugo 0.111.3"><title>nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="nilstriebs blog"><meta property="og:description" content><meta property="og:url" content="/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=posts><div class="post on-list"><h1 class=post-title><a href=/posts/item-patterns-and-struct-else/>Item Patterns And Struct Else</a></h1><div class=post-meta><span class=post-date>2023-03-17</span>
<span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/language-design/>language-design</a>&nbsp;</span><div class=post-content>Bringing more expressiveness to our items</div><div><a class="read-more button" href=/posts/item-patterns-and-struct-else/></a></div></div><div class="post on-list"><h1 class=post-title><a href=/posts/box-is-a-unique-type/>Box Is a Unique Type</a></h1><div class=post-meta><span class=post-date>2022-07-23</span>
<span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp; <span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/unsafe-code/>unsafe code</a>&nbsp;</span><div class=post-content>About better aliasing semantics for <code>Box&lt;T></code></div><div><a class="read-more button" href=/posts/box-is-a-unique-type/></a></div></div><div class=pagination><div class=pagination__buttons></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span> #<a href=/tags/unsafe-code/>unsafe code</a>&nbsp;</span><div class=post-content>About better aliasing semantics for <code>Box&lt;T></code></div><div><a class="read-more button" href=/posts/box-is-a-unique-type/></a></div></div><div class=pagination><div class=pagination__buttons></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span>
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script> <span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>

165
index.xml
View file

@ -1,4 +1,167 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>nilstriebs blog</title><link>/</link><description>Recent content on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sat, 23 Jul 2022 00:00:00 +0000</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml"/><item><title>Box Is a Unique Type</title><link>/posts/box-is-a-unique-type/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/posts/box-is-a-unique-type/</guid><description>We have all used Box&amp;lt;T&amp;gt; before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics and flexibility. We can use it to put our values on the heap, but it can do even more than that! <?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>nilstriebs blog</title><link>/</link><description>Recent content on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 17 Mar 2023 00:00:00 +0000</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml"/><item><title>Item Patterns And Struct Else</title><link>/posts/item-patterns-and-struct-else/</link><pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate><guid>/posts/item-patterns-and-struct-else/</guid><description>Pattern matching One of my favourite features of Rust is pattern matching. It&amp;rsquo;s a simple and elegant way to deal with not just structs, but also enums!
enum ItemKind { Struct(String, Vec&amp;lt;Field&amp;gt;), Function(String, Body), } impl ItemKind { fn name(&amp;amp;self) -&amp;gt; &amp;amp;str { match self { Self::Struct(name, _) =&amp;gt; name, Self::Function(name, _) =&amp;gt; name, } } } Here, we have an enum and a function to get the name out of this.</description><content>&lt;h1 id="pattern-matching">Pattern matching&lt;/h1>
&lt;p>One of my favourite features of Rust is pattern matching. It&amp;rsquo;s a simple and elegant way to deal with not just structs, but also enums!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#a6e22e">ItemKind&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Struct(String, Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>Field&lt;span style="color:#f92672">&amp;gt;&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Function(String, Body),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> ItemKind {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">name&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self) -&amp;gt; &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">match&lt;/span> self {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Self::Struct(name, _) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> name,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Self::Function(name, _) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> name,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we have an enum and a function to get the name out of this. In C, this would be very unsafe, as we cannot be guaranteed that our union has the right tag.
But in Rust, the compiler nicely checks it all for us. It&amp;rsquo;s safe and expressive (just like many other features of Rust).&lt;/p>
&lt;p>But that isn&amp;rsquo;t the only way to use pattern matching. While branching is one of its core features (in that sense, pattern matching is just like git),
it doesn&amp;rsquo;t always have to be used. Another major advantage of pattern matching lies in the ability to &lt;em>exhaustively&lt;/em> (not be be confused with exhausting, like writing down brilliant ideas like this) match over inputs.&lt;/p>
&lt;p>Let&amp;rsquo;s look at the following example. Here, we have a struct representing a struct in a programming language. It has a name and fields.
We then manually implement a custom hash trait for it because we are important and need a custom hash trait. We could have written a derive macro, but didn&amp;rsquo;t because
we don&amp;rsquo;t understand how proc macros work.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields: Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>Field&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> HandRolledHash &lt;span style="color:#66d9ef">for&lt;/span> Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self, hasher: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mut&lt;/span> HandRolledHasher) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self.name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self.fields);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This works perfectly. But then later, &lt;a href="https://github.com/rust-lang/rustup/pull/1642">we add privacy to the language&lt;/a>. Now, all types have a visibility.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-diff" data-lang="diff">&lt;span style="display:flex;">&lt;span>struct Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">+ visibility: Vis,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">&lt;/span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields: Vec&amp;lt;Field&amp;gt;,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Pretty cool. Now no one can access the implementation details and make everything a mess. But wait - we have just made a mess! We didn&amp;rsquo;t hash the visibility!
Hashing something incorrectly &lt;a href="https://github.com/rust-lang/rust/issues/84970">doesn&amp;rsquo;t sound too bad&lt;/a>, but it would be nice if this was prevented.&lt;/p>
&lt;p>Thanks to exhaustive pattern matching, it would have been easy to prevent. We just change our hash implementation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> HandRolledHash &lt;span style="color:#66d9ef">for&lt;/span> Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self, hasher: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mut&lt;/span> HandRolledHasher) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">let&lt;/span> Self { name, fields } &lt;span style="color:#f92672">=&lt;/span> self;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(fields);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And with this, adding the visibility will cause a compiler error and alert us that we need to handle it in hashing.
(The decision whether we actually do want to handle it is still up to us. We could also just turn off the computer and make new friends outside.)&lt;/p>
&lt;p>We can conclude that pattern matching is a great feature.&lt;/p>
&lt;h1 id="limitations-of-pattern-matching">Limitations of pattern matching&lt;/h1>
&lt;p>But there is one big limitation of pattern matching - all of its occurrences (&lt;code>match&lt;/code>, &lt;code>if let&lt;/code>, &lt;code>if let&lt;/code> chains, &lt;code>while let&lt;/code>, &lt;code>while let&lt;/code> chains, &lt;code>for&lt;/code>, &lt;code>let&lt;/code>, &lt;code>let else&lt;/code>, and function parameters
(we do have a lot of pattern matching)) are inside of bodies, mostly as part of expressions or statements.&lt;/p>
&lt;p>This doesn&amp;rsquo;t sound too bad. This is where the executed code resides. But it comes at a cost of consistency. We often add many syntactical niceties to expressions and statements, but forget about items.&lt;/p>
&lt;h1 id="items-and-sadness">Items and sadness&lt;/h1>
&lt;p>Items have a hard life. They are the parents of everything important. &lt;code>struct&lt;/code>, &lt;code>enum&lt;/code>, &lt;code>const&lt;/code>, &lt;code>mod&lt;/code>, &lt;code>fn&lt;/code>, &lt;code>union&lt;/code>, &lt;code>global_asm&lt;/code> are all things we use daily, yet their grammar is very limited. (&amp;ldquo;free the items&amp;rdquo; was an alternative blog post title, although &amp;ldquo;freeing&amp;rdquo; generally remains a concern of &lt;a href="https://nilstrieb.github.io/nilstrieb-c-style-guide-edition-2/">my C style guide&lt;/a>).&lt;/p>
&lt;p>For example, see the following code where we declare a few constants.&lt;/p>
&lt;pre tabindex="0">&lt;code>const ONE: u8 = 1;
const TWO: u8 = 1;
const THREE: u8 = 3;
&lt;/code>&lt;/pre>&lt;p>There is nothing obviously wrong with this code. You understand it, I understand it, an ALGOL 68 developer from 1970 would probably understand it
and even an ancient greek philosopher might have a clue (which is impressive, given that they are all not alive anymore). But this is the kind of code that pages you at 4 AM.&lt;/p>
&lt;p>You&amp;rsquo;ve read the last paragraph in confusion. Of course there&amp;rsquo;s something wrong with this code! &lt;code>TWO&lt;/code> is &lt;code>1&lt;/code>, yet the name strongly suggests that it should be &lt;code>2&lt;/code>. And you&amp;rsquo;d
be right, this was just a check to make sure you&amp;rsquo;re still here. You are very clever and deserve this post. If you didn&amp;rsquo;t notice it, go to sleep. It&amp;rsquo;s good for your health.&lt;/p>
&lt;p>But even if it was &lt;code>2&lt;/code>, this code is still not good. There is way too much duplication! &lt;code>const&lt;/code> is mentioned three times. This is a major distraction to the reader.&lt;/p>
&lt;p>Let&amp;rsquo;s have a harder example:&lt;/p>
&lt;pre tabindex="0">&lt;code>const ONE: u8 = 0; const
NAME: &amp;amp;
str = &amp;#34;nils&amp;#34;;
const X: &amp;amp;str
= &amp;#34;const&amp;#34;;const A: () = ();
&lt;/code>&lt;/pre>&lt;p>Here, the &lt;code>const&lt;/code> being noise is a lot more obvious. Did you see that &lt;code>X&lt;/code> contains &lt;code>&amp;quot;const&amp;quot;&lt;/code>? Maybe you did, maybe you didn&amp;rsquo;t. When I tested it, 0/0 people could see it.&lt;/p>
&lt;p>Now imagine if it looked like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> (&lt;span style="color:#66d9ef">ONE&lt;/span>, &lt;span style="color:#66d9ef">NAME&lt;/span>, X, A): (&lt;span style="color:#66d9ef">u8&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span>, ()) &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;nils&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;const&amp;#34;&lt;/span>, ());
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Everything is way shorter and more readable.&lt;/p>
&lt;p>What you&amp;rsquo;ve just seen is a limited form of pattern matching!&lt;/p>
&lt;h1 id="lets-go-further">Let&amp;rsquo;s go further&lt;/h1>
&lt;p>The idea of generalizing pattern matching is very powerful. We can apply this to more than just consts.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> (Person, Car) &lt;span style="color:#f92672">=&lt;/span> ({ name: String }, { wheels: &lt;span style="color:#66d9ef">u8&lt;/span> });
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we create two structs with just a single &lt;code>struct&lt;/code> keyword. This makes it way simpler and easier to read when related structs are declared.
So far we&amp;rsquo;ve just used tuples. But we can go even further. Structs of structs!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Household&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>T, U&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent: &lt;span style="color:#a6e22e">T&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> child: &lt;span style="color:#a6e22e">U&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Household&lt;/span> { parent: &lt;span style="color:#a6e22e">Ferris&lt;/span>, child: &lt;span style="color:#a6e22e">Corro&lt;/span> } &lt;span style="color:#f92672">=&lt;/span> Household {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent: { name: String },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> child: { name: String, unsafety: &lt;span style="color:#66d9ef">bool&lt;/span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we can nicely match on the &lt;code>Household&lt;/code> struct containing the definition of the &lt;code>Ferris&lt;/code> and &lt;code>Corro&lt;/code> structs. This is equivalent to the following code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Feris&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Corro&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> unsafety: &lt;span style="color:#66d9ef">bool&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is already really neat, but there&amp;rsquo;s more. We also have to consider the falliblity of patterns.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> Some(A) &lt;span style="color:#f92672">=&lt;/span> None;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This pattern doesn&amp;rsquo;t match. Inside bodies, we could use an &lt;code>if let&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">let&lt;/span> Some(a) &lt;span style="color:#f92672">=&lt;/span> None {} &lt;span style="color:#66d9ef">else&lt;/span> {}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can also apply this to items.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> Some(A) &lt;span style="color:#f92672">=&lt;/span> None {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/* other items where A exists */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/* other items where A doesn&amp;#39;t exist */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This doesn&amp;rsquo;t sound too useful, but it allows for extreme flexibility!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>macro_rules&lt;span style="color:#f92672">!&lt;/span> are_same_type {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (&lt;span style="color:#75715e">$a&lt;/span>:&lt;span style="color:#a6e22e">ty&lt;/span>, &lt;span style="color:#75715e">$b&lt;/span>:&lt;span style="color:#a6e22e">ty&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">mut&lt;/span> &lt;span style="color:#66d9ef">ARE_SAME&lt;/span>: &lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#75715e">$a&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#75715e">$b&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> _: () &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">unsafe&lt;/span> { &lt;span style="color:#66d9ef">ARE_SAME&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>; };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">unsafe&lt;/span> { &lt;span style="color:#66d9ef">ARE_SAME&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> are_same_type!(Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>String&lt;span style="color:#f92672">&amp;gt;&lt;/span>, String) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> println!(&lt;span style="color:#e6db74">&amp;#34;impossible to reach!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ignoring this suspicious assignment to a &lt;code>static mut&lt;/code>, this is lovely!&lt;/p>
&lt;p>We can go further.&lt;/p>
&lt;p>Today, items are just there with no ordering. What if we imposed an ordering? (and just like this, the C11 atomic model was born.) What if &amp;ldquo;Rust items&amp;rdquo; was a meta scripting language?&lt;/p>
&lt;p>We can write a simple guessing game!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">fn&lt;/span> input() -&amp;gt; &lt;span style="color:#66d9ef">u8&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span>: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span> &lt;span style="color:#f92672">=&lt;/span> prompt!();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> Ok(&lt;span style="color:#66d9ef">INPUT&lt;/span>): Result&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">u8&lt;/span>, ParseIntErr&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span>.parse() &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_error!(&lt;span style="color:#e6db74">&amp;#34;Invalid input&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">INPUT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span>: &lt;span style="color:#66d9ef">u8&lt;/span> &lt;span style="color:#f92672">=&lt;/span> env!(&lt;span style="color:#e6db74">&amp;#34;RANDOM&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">loop&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">=&lt;/span> input();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>; &lt;span style="color:#75715e">// continue compilation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_warn!(&lt;span style="color:#e6db74">&amp;#34;input is smaller&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_warn!(&lt;span style="color:#e6db74">&amp;#34;input is bigger&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Empty. I am useless. I strike!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If it weren&amp;rsquo;t for &lt;code>fn main&lt;/code> starting a strike and stopping compilation, this would have worked! Quite bold of &lt;code>fn main&lt;/code> to just start a strike, even though there&amp;rsquo;s no &lt;code>union&lt;/code> in the entire program. But we really need it, it&amp;rsquo;s not a disposable worker.&lt;/p>
&lt;p>And then, last and least I want to highlight one of my favourite consequences of this: &lt;code>struct else&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> Some(Test) &lt;span style="color:#f92672">=&lt;/span> None &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_error!(&lt;span style="color:#e6db74">&amp;#34;didn&amp;#39;t match pattern&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;!-- raw HTML omitted -->you&amp;rsquo;re asking yourself what you just read. meanwhile, i am asking myself what i just wrote. we are very similar.&lt;!-- raw HTML omitted -->&lt;/p></content></item><item><title>Box Is a Unique Type</title><link>/posts/box-is-a-unique-type/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/posts/box-is-a-unique-type/</guid><description>We have all used Box&amp;lt;T&amp;gt; before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics and flexibility. We can use it to put our values on the heap, but it can do even more than that!
struct Fields { a: String, b: String, } let fields = Box::new(Fields { a: &amp;#34;a&amp;#34;.to_string(), b: &amp;#34;b&amp;#34;.to_string() }); let a = fields.a; let b = fields.b; This kind of partial deref move is just one of the spectacular magic tricks box has up its sleeve, and they exist for good reason: They are very useful.</description><content>&lt;p>We have all used &lt;code>Box&amp;lt;T&amp;gt;&lt;/code> before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics struct Fields { a: String, b: String, } let fields = Box::new(Fields { a: &amp;#34;a&amp;#34;.to_string(), b: &amp;#34;b&amp;#34;.to_string() }); let a = fields.a; let b = fields.b; This kind of partial deref move is just one of the spectacular magic tricks box has up its sleeve, and they exist for good reason: They are very useful.</description><content>&lt;p>We have all used &lt;code>Box&amp;lt;T&amp;gt;&lt;/code> before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics
and flexibility. We can use it to put our values on the heap, but it can do even more and flexibility. We can use it to put our values on the heap, but it can do even more
than that!&lt;/p> than that!&lt;/p>

View file

@ -131,6 +131,7 @@ are very strong, and still giving code an option to obtain these seems useful. O
<code>&'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href=https://github.com/rust-lang/unsafe-code-guidelines/issues/316>unclear</a>. <code>&'static mut T</code> that is unleaked for drop, but the semantics of this are still <a href=https://github.com/rust-lang/unsafe-code-guidelines/issues/316>unclear</a>.
If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code> If that is not possible, exposing <code>std::ptr::Unique</code> (with it getting boxes aliasing semantics) could be desirable. For this, all existing usages of <code>Unique</code>
inside the standard library would have to be removed. We could also offer a <code>std::boxed::UniqueBox</code> that keeps the current semantics, but this would also bring direct aliasing inside the standard library would have to be removed. We could also offer a <code>std::boxed::UniqueBox</code> that keeps the current semantics, but this would also bring direct aliasing
decisions more towards safe code, which I am not a huge fan of. Ownership is enough already.</p><p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&mldr;</p><p>For more information about this topic, see <a href=https://github.com/rust-lang/unsafe-code-guidelines/issues/326>https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p><p><em>Thanks to the nice people on the Rust Community Discord for their feedback on the draft of this post!</em></p></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span> decisions more towards safe code, which I am not a huge fan of. Ownership is enough already.</p><p>I guess what I am wishing for are some good and flexible raw pointer types. But that&rsquo;s still in the stars&mldr;</p><p>For more information about this topic, see <a href=https://github.com/rust-lang/unsafe-code-guidelines/issues/326>https://github.com/rust-lang/unsafe-code-guidelines/issues/326</a></p><p><em>Thanks to the nice people on the Rust Community Discord for their feedback on the draft of this post!</em></p></div></div><div class=pagination><div class=pagination__title><span class=pagination__title-h></span><hr></div><div class=pagination__buttons><span class="button previous"><a href=/posts/item-patterns-and-struct-else/><span class=button__icon></span>
<span class=button__text>Item Patterns And Struct Else</span></a></span></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span>
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script> <span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>
<script src=/assets/prism.js></script></div></body></html> <script src=/assets/prism.js></script></div></body></html>

View file

@ -1,4 +1,6 @@
<!doctype html><html lang=en><head><title>Posts :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/posts/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="Posts"><meta property="og:description" content><meta property="og:url" content="/posts/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/posts/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=posts><div class="post on-list"><h1 class=post-title><a href=/posts/box-is-a-unique-type/>Box Is a Unique Type</a></h1><div class=post-meta><span class=post-date>2022-07-23</span> <!doctype html><html lang=en><head><title>Posts :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/posts/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="Posts"><meta property="og:description" content><meta property="og:url" content="/posts/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/posts/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=posts><div class="post on-list"><h1 class=post-title><a href=/posts/item-patterns-and-struct-else/>Item Patterns And Struct Else</a></h1><div class=post-meta><span class=post-date>2023-03-17</span>
<span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/language-design/>language-design</a>&nbsp;</span><div class=post-content>Bringing more expressiveness to our items</div><div><a class="read-more button" href=/posts/item-patterns-and-struct-else/></a></div></div><div class="post on-list"><h1 class=post-title><a href=/posts/box-is-a-unique-type/>Box Is a Unique Type</a></h1><div class=post-meta><span class=post-date>2022-07-23</span>
<span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp; <span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/unsafe-code/>unsafe code</a>&nbsp;</span><div class=post-content>About better aliasing semantics for <code>Box&lt;T></code></div><div><a class="read-more button" href=/posts/box-is-a-unique-type/></a></div></div><div class=pagination><div class=pagination__buttons></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span> #<a href=/tags/unsafe-code/>unsafe code</a>&nbsp;</span><div class=post-content>About better aliasing semantics for <code>Box&lt;T></code></div><div><a class="read-more button" href=/posts/box-is-a-unique-type/></a></div></div><div class=pagination><div class=pagination__buttons></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span>
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script> <span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>

View file

@ -1,4 +1,167 @@
<?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 nilstriebs blog</title><link>/posts/</link><description>Recent content in Posts on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sat, 23 Jul 2022 00:00:00 +0000</lastBuildDate><atom:link href="/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Box Is a Unique Type</title><link>/posts/box-is-a-unique-type/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/posts/box-is-a-unique-type/</guid><description>We have all used Box&amp;lt;T&amp;gt; before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics and flexibility. We can use it to put our values on the heap, but it can do even more than that! <?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 nilstriebs blog</title><link>/posts/</link><description>Recent content in Posts on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 17 Mar 2023 00:00:00 +0000</lastBuildDate><atom:link href="/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Item Patterns And Struct Else</title><link>/posts/item-patterns-and-struct-else/</link><pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate><guid>/posts/item-patterns-and-struct-else/</guid><description>Pattern matching One of my favourite features of Rust is pattern matching. It&amp;rsquo;s a simple and elegant way to deal with not just structs, but also enums!
enum ItemKind { Struct(String, Vec&amp;lt;Field&amp;gt;), Function(String, Body), } impl ItemKind { fn name(&amp;amp;self) -&amp;gt; &amp;amp;str { match self { Self::Struct(name, _) =&amp;gt; name, Self::Function(name, _) =&amp;gt; name, } } } Here, we have an enum and a function to get the name out of this.</description><content>&lt;h1 id="pattern-matching">Pattern matching&lt;/h1>
&lt;p>One of my favourite features of Rust is pattern matching. It&amp;rsquo;s a simple and elegant way to deal with not just structs, but also enums!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#a6e22e">ItemKind&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Struct(String, Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>Field&lt;span style="color:#f92672">&amp;gt;&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Function(String, Body),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> ItemKind {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">name&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self) -&amp;gt; &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">match&lt;/span> self {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Self::Struct(name, _) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> name,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Self::Function(name, _) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> name,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we have an enum and a function to get the name out of this. In C, this would be very unsafe, as we cannot be guaranteed that our union has the right tag.
But in Rust, the compiler nicely checks it all for us. It&amp;rsquo;s safe and expressive (just like many other features of Rust).&lt;/p>
&lt;p>But that isn&amp;rsquo;t the only way to use pattern matching. While branching is one of its core features (in that sense, pattern matching is just like git),
it doesn&amp;rsquo;t always have to be used. Another major advantage of pattern matching lies in the ability to &lt;em>exhaustively&lt;/em> (not be be confused with exhausting, like writing down brilliant ideas like this) match over inputs.&lt;/p>
&lt;p>Let&amp;rsquo;s look at the following example. Here, we have a struct representing a struct in a programming language. It has a name and fields.
We then manually implement a custom hash trait for it because we are important and need a custom hash trait. We could have written a derive macro, but didn&amp;rsquo;t because
we don&amp;rsquo;t understand how proc macros work.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields: Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>Field&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> HandRolledHash &lt;span style="color:#66d9ef">for&lt;/span> Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self, hasher: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mut&lt;/span> HandRolledHasher) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self.name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self.fields);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This works perfectly. But then later, &lt;a href="https://github.com/rust-lang/rustup/pull/1642">we add privacy to the language&lt;/a>. Now, all types have a visibility.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-diff" data-lang="diff">&lt;span style="display:flex;">&lt;span>struct Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">+ visibility: Vis,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">&lt;/span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields: Vec&amp;lt;Field&amp;gt;,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Pretty cool. Now no one can access the implementation details and make everything a mess. But wait - we have just made a mess! We didn&amp;rsquo;t hash the visibility!
Hashing something incorrectly &lt;a href="https://github.com/rust-lang/rust/issues/84970">doesn&amp;rsquo;t sound too bad&lt;/a>, but it would be nice if this was prevented.&lt;/p>
&lt;p>Thanks to exhaustive pattern matching, it would have been easy to prevent. We just change our hash implementation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> HandRolledHash &lt;span style="color:#66d9ef">for&lt;/span> Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self, hasher: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mut&lt;/span> HandRolledHasher) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">let&lt;/span> Self { name, fields } &lt;span style="color:#f92672">=&lt;/span> self;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(fields);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And with this, adding the visibility will cause a compiler error and alert us that we need to handle it in hashing.
(The decision whether we actually do want to handle it is still up to us. We could also just turn off the computer and make new friends outside.)&lt;/p>
&lt;p>We can conclude that pattern matching is a great feature.&lt;/p>
&lt;h1 id="limitations-of-pattern-matching">Limitations of pattern matching&lt;/h1>
&lt;p>But there is one big limitation of pattern matching - all of its occurrences (&lt;code>match&lt;/code>, &lt;code>if let&lt;/code>, &lt;code>if let&lt;/code> chains, &lt;code>while let&lt;/code>, &lt;code>while let&lt;/code> chains, &lt;code>for&lt;/code>, &lt;code>let&lt;/code>, &lt;code>let else&lt;/code>, and function parameters
(we do have a lot of pattern matching)) are inside of bodies, mostly as part of expressions or statements.&lt;/p>
&lt;p>This doesn&amp;rsquo;t sound too bad. This is where the executed code resides. But it comes at a cost of consistency. We often add many syntactical niceties to expressions and statements, but forget about items.&lt;/p>
&lt;h1 id="items-and-sadness">Items and sadness&lt;/h1>
&lt;p>Items have a hard life. They are the parents of everything important. &lt;code>struct&lt;/code>, &lt;code>enum&lt;/code>, &lt;code>const&lt;/code>, &lt;code>mod&lt;/code>, &lt;code>fn&lt;/code>, &lt;code>union&lt;/code>, &lt;code>global_asm&lt;/code> are all things we use daily, yet their grammar is very limited. (&amp;ldquo;free the items&amp;rdquo; was an alternative blog post title, although &amp;ldquo;freeing&amp;rdquo; generally remains a concern of &lt;a href="https://nilstrieb.github.io/nilstrieb-c-style-guide-edition-2/">my C style guide&lt;/a>).&lt;/p>
&lt;p>For example, see the following code where we declare a few constants.&lt;/p>
&lt;pre tabindex="0">&lt;code>const ONE: u8 = 1;
const TWO: u8 = 1;
const THREE: u8 = 3;
&lt;/code>&lt;/pre>&lt;p>There is nothing obviously wrong with this code. You understand it, I understand it, an ALGOL 68 developer from 1970 would probably understand it
and even an ancient greek philosopher might have a clue (which is impressive, given that they are all not alive anymore). But this is the kind of code that pages you at 4 AM.&lt;/p>
&lt;p>You&amp;rsquo;ve read the last paragraph in confusion. Of course there&amp;rsquo;s something wrong with this code! &lt;code>TWO&lt;/code> is &lt;code>1&lt;/code>, yet the name strongly suggests that it should be &lt;code>2&lt;/code>. And you&amp;rsquo;d
be right, this was just a check to make sure you&amp;rsquo;re still here. You are very clever and deserve this post. If you didn&amp;rsquo;t notice it, go to sleep. It&amp;rsquo;s good for your health.&lt;/p>
&lt;p>But even if it was &lt;code>2&lt;/code>, this code is still not good. There is way too much duplication! &lt;code>const&lt;/code> is mentioned three times. This is a major distraction to the reader.&lt;/p>
&lt;p>Let&amp;rsquo;s have a harder example:&lt;/p>
&lt;pre tabindex="0">&lt;code>const ONE: u8 = 0; const
NAME: &amp;amp;
str = &amp;#34;nils&amp;#34;;
const X: &amp;amp;str
= &amp;#34;const&amp;#34;;const A: () = ();
&lt;/code>&lt;/pre>&lt;p>Here, the &lt;code>const&lt;/code> being noise is a lot more obvious. Did you see that &lt;code>X&lt;/code> contains &lt;code>&amp;quot;const&amp;quot;&lt;/code>? Maybe you did, maybe you didn&amp;rsquo;t. When I tested it, 0/0 people could see it.&lt;/p>
&lt;p>Now imagine if it looked like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> (&lt;span style="color:#66d9ef">ONE&lt;/span>, &lt;span style="color:#66d9ef">NAME&lt;/span>, X, A): (&lt;span style="color:#66d9ef">u8&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span>, ()) &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;nils&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;const&amp;#34;&lt;/span>, ());
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Everything is way shorter and more readable.&lt;/p>
&lt;p>What you&amp;rsquo;ve just seen is a limited form of pattern matching!&lt;/p>
&lt;h1 id="lets-go-further">Let&amp;rsquo;s go further&lt;/h1>
&lt;p>The idea of generalizing pattern matching is very powerful. We can apply this to more than just consts.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> (Person, Car) &lt;span style="color:#f92672">=&lt;/span> ({ name: String }, { wheels: &lt;span style="color:#66d9ef">u8&lt;/span> });
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we create two structs with just a single &lt;code>struct&lt;/code> keyword. This makes it way simpler and easier to read when related structs are declared.
So far we&amp;rsquo;ve just used tuples. But we can go even further. Structs of structs!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Household&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>T, U&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent: &lt;span style="color:#a6e22e">T&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> child: &lt;span style="color:#a6e22e">U&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Household&lt;/span> { parent: &lt;span style="color:#a6e22e">Ferris&lt;/span>, child: &lt;span style="color:#a6e22e">Corro&lt;/span> } &lt;span style="color:#f92672">=&lt;/span> Household {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent: { name: String },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> child: { name: String, unsafety: &lt;span style="color:#66d9ef">bool&lt;/span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we can nicely match on the &lt;code>Household&lt;/code> struct containing the definition of the &lt;code>Ferris&lt;/code> and &lt;code>Corro&lt;/code> structs. This is equivalent to the following code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Feris&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Corro&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> unsafety: &lt;span style="color:#66d9ef">bool&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is already really neat, but there&amp;rsquo;s more. We also have to consider the falliblity of patterns.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> Some(A) &lt;span style="color:#f92672">=&lt;/span> None;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This pattern doesn&amp;rsquo;t match. Inside bodies, we could use an &lt;code>if let&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">let&lt;/span> Some(a) &lt;span style="color:#f92672">=&lt;/span> None {} &lt;span style="color:#66d9ef">else&lt;/span> {}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can also apply this to items.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> Some(A) &lt;span style="color:#f92672">=&lt;/span> None {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/* other items where A exists */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/* other items where A doesn&amp;#39;t exist */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This doesn&amp;rsquo;t sound too useful, but it allows for extreme flexibility!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>macro_rules&lt;span style="color:#f92672">!&lt;/span> are_same_type {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (&lt;span style="color:#75715e">$a&lt;/span>:&lt;span style="color:#a6e22e">ty&lt;/span>, &lt;span style="color:#75715e">$b&lt;/span>:&lt;span style="color:#a6e22e">ty&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">mut&lt;/span> &lt;span style="color:#66d9ef">ARE_SAME&lt;/span>: &lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#75715e">$a&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#75715e">$b&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> _: () &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">unsafe&lt;/span> { &lt;span style="color:#66d9ef">ARE_SAME&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>; };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">unsafe&lt;/span> { &lt;span style="color:#66d9ef">ARE_SAME&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> are_same_type!(Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>String&lt;span style="color:#f92672">&amp;gt;&lt;/span>, String) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> println!(&lt;span style="color:#e6db74">&amp;#34;impossible to reach!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ignoring this suspicious assignment to a &lt;code>static mut&lt;/code>, this is lovely!&lt;/p>
&lt;p>We can go further.&lt;/p>
&lt;p>Today, items are just there with no ordering. What if we imposed an ordering? (and just like this, the C11 atomic model was born.) What if &amp;ldquo;Rust items&amp;rdquo; was a meta scripting language?&lt;/p>
&lt;p>We can write a simple guessing game!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">fn&lt;/span> input() -&amp;gt; &lt;span style="color:#66d9ef">u8&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span>: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span> &lt;span style="color:#f92672">=&lt;/span> prompt!();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> Ok(&lt;span style="color:#66d9ef">INPUT&lt;/span>): Result&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">u8&lt;/span>, ParseIntErr&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span>.parse() &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_error!(&lt;span style="color:#e6db74">&amp;#34;Invalid input&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">INPUT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span>: &lt;span style="color:#66d9ef">u8&lt;/span> &lt;span style="color:#f92672">=&lt;/span> env!(&lt;span style="color:#e6db74">&amp;#34;RANDOM&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">loop&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">=&lt;/span> input();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>; &lt;span style="color:#75715e">// continue compilation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_warn!(&lt;span style="color:#e6db74">&amp;#34;input is smaller&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_warn!(&lt;span style="color:#e6db74">&amp;#34;input is bigger&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Empty. I am useless. I strike!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If it weren&amp;rsquo;t for &lt;code>fn main&lt;/code> starting a strike and stopping compilation, this would have worked! Quite bold of &lt;code>fn main&lt;/code> to just start a strike, even though there&amp;rsquo;s no &lt;code>union&lt;/code> in the entire program. But we really need it, it&amp;rsquo;s not a disposable worker.&lt;/p>
&lt;p>And then, last and least I want to highlight one of my favourite consequences of this: &lt;code>struct else&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> Some(Test) &lt;span style="color:#f92672">=&lt;/span> None &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_error!(&lt;span style="color:#e6db74">&amp;#34;didn&amp;#39;t match pattern&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;!-- raw HTML omitted -->you&amp;rsquo;re asking yourself what you just read. meanwhile, i am asking myself what i just wrote. we are very similar.&lt;!-- raw HTML omitted -->&lt;/p></content></item><item><title>Box Is a Unique Type</title><link>/posts/box-is-a-unique-type/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/posts/box-is-a-unique-type/</guid><description>We have all used Box&amp;lt;T&amp;gt; before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics and flexibility. We can use it to put our values on the heap, but it can do even more than that!
struct Fields { a: String, b: String, } let fields = Box::new(Fields { a: &amp;#34;a&amp;#34;.to_string(), b: &amp;#34;b&amp;#34;.to_string() }); let a = fields.a; let b = fields.b; This kind of partial deref move is just one of the spectacular magic tricks box has up its sleeve, and they exist for good reason: They are very useful.</description><content>&lt;p>We have all used &lt;code>Box&amp;lt;T&amp;gt;&lt;/code> before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics struct Fields { a: String, b: String, } let fields = Box::new(Fields { a: &amp;#34;a&amp;#34;.to_string(), b: &amp;#34;b&amp;#34;.to_string() }); let a = fields.a; let b = fields.b; This kind of partial deref move is just one of the spectacular magic tricks box has up its sleeve, and they exist for good reason: They are very useful.</description><content>&lt;p>We have all used &lt;code>Box&amp;lt;T&amp;gt;&lt;/code> before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics
and flexibility. We can use it to put our values on the heap, but it can do even more and flexibility. We can use it to put our values on the heap, but it can do even more
than that!&lt;/p> than that!&lt;/p>

View file

@ -0,0 +1,131 @@
<!doctype html><html lang=en><head><title>Item Patterns And Struct Else :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content="Bringing more expressiveness to our items"><meta name=keywords content="design"><meta name=robots content="noodp"><link rel=canonical href=/posts/item-patterns-and-struct-else/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="article"><meta property="og:title" content="Item Patterns And Struct Else"><meta property="og:description" content="Bringing more expressiveness to our items"><meta property="og:url" content="/posts/item-patterns-and-struct-else/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><meta property="article:published_time" content="2023-03-17 00:00:00 +0000 UTC"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=post><h1 class=post-title><a href=/posts/item-patterns-and-struct-else/>Item Patterns And Struct Else</a></h1><div class=post-meta><span class=post-date>2023-03-17</span>
<span class=post-author>:: Nilstrieb</span>
<span class=post-reading-time>:: 7 min read (1351 words)</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/language-design/>language-design</a>&nbsp;</span><div class=post-content><div><h1 id=pattern-matching>Pattern matching<a href=#pattern-matching class=hanchor arialabel=Anchor>&#8983;</a></h1><p>One of my favourite features of Rust is pattern matching. It&rsquo;s a simple and elegant way to deal with not just structs, but also enums!</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>enum</span> <span style=color:#a6e22e>ItemKind</span> {
</span></span><span style=display:flex><span> Struct(String, Vec<span style=color:#f92672>&lt;</span>Field<span style=color:#f92672>&gt;</span>),
</span></span><span style=display:flex><span> Function(String, Body),
</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>impl</span> ItemKind {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>name</span>(<span style=color:#f92672>&amp;</span>self) -&gt; <span style=color:#66d9ef>&amp;</span><span style=color:#66d9ef>str</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>match</span> self {
</span></span><span style=display:flex><span> Self::Struct(name, _) <span style=color:#f92672>=&gt;</span> name,
</span></span><span style=display:flex><span> Self::Function(name, _) <span style=color:#f92672>=&gt;</span> name,
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Here, we have an enum and a function to get the name out of this. In C, this would be very unsafe, as we cannot be guaranteed that our union has the right tag.
But in Rust, the compiler nicely checks it all for us. It&rsquo;s safe and expressive (just like many other features of Rust).</p><p>But that isn&rsquo;t the only way to use pattern matching. While branching is one of its core features (in that sense, pattern matching is just like git),
it doesn&rsquo;t always have to be used. Another major advantage of pattern matching lies in the ability to <em>exhaustively</em> (not be be confused with exhausting, like writing down brilliant ideas like this) match over inputs.</p><p>Let&rsquo;s look at the following example. Here, we have a struct representing a struct in a programming language. It has a name and fields.
We then manually implement a custom hash trait for it because we are important and need a custom hash trait. We could have written a derive macro, but didn&rsquo;t because
we don&rsquo;t understand how proc macros 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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>Struct</span> {
</span></span><span style=display:flex><span> name: String,
</span></span><span style=display:flex><span> fields: Vec<span style=color:#f92672>&lt;</span>Field<span style=color:#f92672>&gt;</span>,
</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>impl</span> HandRolledHash <span style=color:#66d9ef>for</span> Struct {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>hash</span>(<span style=color:#f92672>&amp;</span>self, hasher: <span style=color:#66d9ef>&amp;</span><span style=color:#a6e22e>mut</span> HandRolledHasher) {
</span></span><span style=display:flex><span> hasher.hash(<span style=color:#f92672>&amp;</span>self.name);
</span></span><span style=display:flex><span> hasher.hash(<span style=color:#f92672>&amp;</span>self.fields);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>This works perfectly. But then later, <a href=https://github.com/rust-lang/rustup/pull/1642>we add privacy to the language</a>. Now, all types have a visibility.</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-diff data-lang=diff><span style=display:flex><span>struct Struct {
</span></span><span style=display:flex><span><span style=color:#a6e22e>+ visibility: Vis,
</span></span></span><span style=display:flex><span><span style=color:#a6e22e></span> name: String,
</span></span><span style=display:flex><span> fields: Vec&lt;Field&gt;,
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Pretty cool. Now no one can access the implementation details and make everything a mess. But wait - we have just made a mess! We didn&rsquo;t hash the visibility!
Hashing something incorrectly <a href=https://github.com/rust-lang/rust/issues/84970>doesn&rsquo;t sound too bad</a>, but it would be nice if this was prevented.</p><p>Thanks to exhaustive pattern matching, it would have been easy to prevent. We just change our hash implementation:</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>impl</span> HandRolledHash <span style=color:#66d9ef>for</span> Struct {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>fn</span> <span style=color:#a6e22e>hash</span>(<span style=color:#f92672>&amp;</span>self, hasher: <span style=color:#66d9ef>&amp;</span><span style=color:#a6e22e>mut</span> HandRolledHasher) {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>let</span> Self { name, fields } <span style=color:#f92672>=</span> self;
</span></span><span style=display:flex><span> hasher.hash(name);
</span></span><span style=display:flex><span> hasher.hash(fields);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>And with this, adding the visibility will cause a compiler error and alert us that we need to handle it in hashing.
(The decision whether we actually do want to handle it is still up to us. We could also just turn off the computer and make new friends outside.)</p><p>We can conclude that pattern matching is a great feature.</p><h1 id=limitations-of-pattern-matching>Limitations of pattern matching<a href=#limitations-of-pattern-matching class=hanchor arialabel=Anchor>&#8983;</a></h1><p>But there is one big limitation of pattern matching - all of its occurrences (<code>match</code>, <code>if let</code>, <code>if let</code> chains, <code>while let</code>, <code>while let</code> chains, <code>for</code>, <code>let</code>, <code>let else</code>, and function parameters
(we do have a lot of pattern matching)) are inside of bodies, mostly as part of expressions or statements.</p><p>This doesn&rsquo;t sound too bad. This is where the executed code resides. But it comes at a cost of consistency. We often add many syntactical niceties to expressions and statements, but forget about items.</p><h1 id=items-and-sadness>Items and sadness<a href=#items-and-sadness class=hanchor arialabel=Anchor>&#8983;</a></h1><p>Items have a hard life. They are the parents of everything important. <code>struct</code>, <code>enum</code>, <code>const</code>, <code>mod</code>, <code>fn</code>, <code>union</code>, <code>global_asm</code> are all things we use daily, yet their grammar is very limited. (&ldquo;free the items&rdquo; was an alternative blog post title, although &ldquo;freeing&rdquo; generally remains a concern of <a href=https://nilstrieb.github.io/nilstrieb-c-style-guide-edition-2/>my C style guide</a>).</p><p>For example, see the following code where we declare a few constants.</p><pre tabindex=0><code>const ONE: u8 = 1;
const TWO: u8 = 1;
const THREE: u8 = 3;
</code></pre><p>There is nothing obviously wrong with this code. You understand it, I understand it, an ALGOL 68 developer from 1970 would probably understand it
and even an ancient greek philosopher might have a clue (which is impressive, given that they are all not alive anymore). But this is the kind of code that pages you at 4 AM.</p><p>You&rsquo;ve read the last paragraph in confusion. Of course there&rsquo;s something wrong with this code! <code>TWO</code> is <code>1</code>, yet the name strongly suggests that it should be <code>2</code>. And you&rsquo;d
be right, this was just a check to make sure you&rsquo;re still here. You are very clever and deserve this post. If you didn&rsquo;t notice it, go to sleep. It&rsquo;s good for your health.</p><p>But even if it was <code>2</code>, this code is still not good. There is way too much duplication! <code>const</code> is mentioned three times. This is a major distraction to the reader.</p><p>Let&rsquo;s have a harder example:</p><pre tabindex=0><code>const ONE: u8 = 0; const
NAME: &amp;
str = &#34;nils&#34;;
const X: &amp;str
= &#34;const&#34;;const A: () = ();
</code></pre><p>Here, the <code>const</code> being noise is a lot more obvious. Did you see that <code>X</code> contains <code>"const"</code>? Maybe you did, maybe you didn&rsquo;t. When I tested it, 0/0 people could see it.</p><p>Now imagine if it looked like this:</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>const</span> (<span style=color:#66d9ef>ONE</span>, <span style=color:#66d9ef>NAME</span>, X, A): (<span style=color:#66d9ef>u8</span>, <span style=color:#f92672>&amp;</span><span style=color:#66d9ef>str</span>, <span style=color:#f92672>&amp;</span><span style=color:#66d9ef>str</span>, ()) <span style=color:#f92672>=</span> (<span style=color:#ae81ff>0</span>, <span style=color:#e6db74>&#34;nils&#34;</span>, <span style=color:#e6db74>&#34;const&#34;</span>, ());
</span></span></code></pre></div><p>Everything is way shorter and more readable.</p><p>What you&rsquo;ve just seen is a limited form of pattern matching!</p><h1 id=lets-go-further>Let&rsquo;s go further<a href=#lets-go-further class=hanchor arialabel=Anchor>&#8983;</a></h1><p>The idea of generalizing pattern matching is very powerful. We can apply this to more than just consts.</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>struct</span> (Person, Car) <span style=color:#f92672>=</span> ({ name: String }, { wheels: <span style=color:#66d9ef>u8</span> });
</span></span></code></pre></div><p>Here, we create two structs with just a single <code>struct</code> keyword. This makes it way simpler and easier to read when related structs are declared.
So far we&rsquo;ve just used tuples. But we can go even further. Structs of structs!</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>Household</span><span style=color:#f92672>&lt;</span>T, U<span style=color:#f92672>&gt;</span> {
</span></span><span style=display:flex><span> parent: <span style=color:#a6e22e>T</span>,
</span></span><span style=display:flex><span> child: <span style=color:#a6e22e>U</span>,
</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>struct</span> <span style=color:#a6e22e>Household</span> { parent: <span style=color:#a6e22e>Ferris</span>, child: <span style=color:#a6e22e>Corro</span> } <span style=color:#f92672>=</span> Household {
</span></span><span style=display:flex><span> parent: { name: String },
</span></span><span style=display:flex><span> child: { name: String, unsafety: <span style=color:#66d9ef>bool</span> },
</span></span><span style=display:flex><span>};
</span></span></code></pre></div><p>Now we can nicely match on the <code>Household</code> struct containing the definition of the <code>Ferris</code> and <code>Corro</code> structs. This is equivalent to the following 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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>Feris</span> {
</span></span><span style=display:flex><span> name: String,
</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>struct</span> <span style=color:#a6e22e>Corro</span> {
</span></span><span style=display:flex><span> name: String,
</span></span><span style=display:flex><span> unsafety: <span style=color:#66d9ef>bool</span>,
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>This is already really neat, but there&rsquo;s more. We also have to consider the falliblity of patterns.</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>static</span> Some(A) <span style=color:#f92672>=</span> None;
</span></span></code></pre></div><p>This pattern doesn&rsquo;t match. Inside bodies, we could use an <code>if let</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#66d9ef>let</span> Some(a) <span style=color:#f92672>=</span> None {} <span style=color:#66d9ef>else</span> {}
</span></span></code></pre></div><p>We can also apply this to items.</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>if</span> <span style=color:#66d9ef>struct</span> Some(A) <span style=color:#f92672>=</span> None {
</span></span><span style=display:flex><span> <span style=color:#75715e>/* other items where A exists */</span>
</span></span><span style=display:flex><span>} <span style=color:#66d9ef>else</span> {
</span></span><span style=display:flex><span> <span style=color:#75715e>/* other items where A doesn&#39;t exist */</span>
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>This doesn&rsquo;t sound too useful, but it allows for extreme flexibility!</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-rust data-lang=rust><span style=display:flex><span>macro_rules<span style=color:#f92672>!</span> are_same_type {
</span></span><span style=display:flex><span> (<span style=color:#75715e>$a</span>:<span style=color:#a6e22e>ty</span>, <span style=color:#75715e>$b</span>:<span style=color:#a6e22e>ty</span>) <span style=color:#f92672>=&gt;</span> {{
</span></span><span style=display:flex><span> <span style=color:#66d9ef>static</span> <span style=color:#66d9ef>mut</span> <span style=color:#66d9ef>ARE_SAME</span>: <span style=color:#66d9ef>bool</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>false</span>;
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#66d9ef>struct</span> <span style=color:#75715e>$a</span> <span style=color:#f92672>=</span> <span style=color:#75715e>$b</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>const</span> _: () <span style=color:#f92672>=</span> <span style=color:#66d9ef>unsafe</span> { <span style=color:#66d9ef>ARE_SAME</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>true</span>; };
</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>unsafe</span> { <span style=color:#66d9ef>ARE_SAME</span> }
</span></span><span style=display:flex><span> }};
</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>fn</span> <span style=color:#a6e22e>main</span>() {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> are_same_type!(Vec<span style=color:#f92672>&lt;</span>String<span style=color:#f92672>&gt;</span>, String) {
</span></span><span style=display:flex><span> println!(<span style=color:#e6db74>&#34;impossible to reach!&#34;</span>);
</span></span><span style=display:flex><span> }
</span></span><span style=display:flex><span>}
</span></span></code></pre></div><p>Ignoring this suspicious assignment to a <code>static mut</code>, this is lovely!</p><p>We can go further.</p><p>Today, items are just there with no ordering. What if we imposed an ordering? (and just like this, the C11 atomic model was born.) What if &ldquo;Rust items&rdquo; was a meta scripting language?</p><p>We can write a simple guessing game!</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>struct</span> <span style=color:#a6e22e>fn</span> input() -&gt; <span style=color:#66d9ef>u8</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>const</span> <span style=color:#66d9ef>INPUT</span>: <span style=color:#66d9ef>&amp;</span><span style=color:#66d9ef>str</span> <span style=color:#f92672>=</span> prompt!();
</span></span><span style=display:flex><span> <span style=color:#66d9ef>const</span> Ok(<span style=color:#66d9ef>INPUT</span>): Result<span style=color:#f92672>&lt;</span><span style=color:#66d9ef>u8</span>, ParseIntErr<span style=color:#f92672>&gt;</span> <span style=color:#f92672>=</span> <span style=color:#66d9ef>INPUT</span>.parse() <span style=color:#66d9ef>else</span> {
</span></span><span style=display:flex><span> compile_error!(<span style=color:#e6db74>&#34;Invalid input&#34;</span>);
</span></span><span style=display:flex><span> };
</span></span><span style=display:flex><span> <span style=color:#66d9ef>INPUT</span>
</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>const</span> <span style=color:#66d9ef>RANDOM</span>: <span style=color:#66d9ef>u8</span> <span style=color:#f92672>=</span> env!(<span style=color:#e6db74>&#34;RANDOM&#34;</span>);
</span></span><span style=display:flex><span>
</span></span><span style=display:flex><span><span style=color:#66d9ef>loop</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>const</span> <span style=color:#66d9ef>INPUT</span> <span style=color:#f92672>=</span> input();
</span></span><span style=display:flex><span> <span style=color:#66d9ef>if</span> <span style=color:#66d9ef>INPUT</span> <span style=color:#f92672>==</span> <span style=color:#66d9ef>RANDOM</span> {
</span></span><span style=display:flex><span> <span style=color:#66d9ef>break</span>; <span style=color:#75715e>// continue compilation
</span></span></span><span style=display:flex><span><span style=color:#75715e></span> } <span style=color:#66d9ef>else</span> <span style=color:#66d9ef>if</span> <span style=color:#66d9ef>INPUT</span> <span style=color:#f92672>&lt;</span> <span style=color:#66d9ef>RANDOM</span> {
</span></span><span style=display:flex><span> compile_warn!(<span style=color:#e6db74>&#34;input is smaller&#34;</span>);
</span></span><span style=display:flex><span> } <span style=color:#66d9ef>else</span> {
</span></span><span style=display:flex><span> compile_warn!(<span style=color:#e6db74>&#34;input is bigger&#34;</span>);
</span></span><span style=display:flex><span> }
</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>fn</span> <span style=color:#a6e22e>main</span>() {
</span></span><span style=display:flex><span> <span style=color:#75715e>// Empty. I am useless. I strike!
</span></span></span><span style=display:flex><span><span style=color:#75715e></span>}
</span></span></code></pre></div><p>If it weren&rsquo;t for <code>fn main</code> starting a strike and stopping compilation, this would have worked! Quite bold of <code>fn main</code> to just start a strike, even though there&rsquo;s no <code>union</code> in the entire program. But we really need it, it&rsquo;s not a disposable worker.</p><p>And then, last and least I want to highlight one of my favourite consequences of this: <code>struct else</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-rust data-lang=rust><span style=display:flex><span><span style=color:#66d9ef>struct</span> Some(Test) <span style=color:#f92672>=</span> None <span style=color:#66d9ef>else</span> {
</span></span><span style=display:flex><span> compile_error!(<span style=color:#e6db74>&#34;didn&#39;t match pattern&#34;</span>);
</span></span><span style=display:flex><span>};
</span></span></code></pre></div><p>you&rsquo;re asking yourself what you just read. meanwhile, i am asking myself what i just wrote. we are very similar.</p></div></div><div class=pagination><div class=pagination__title><span class=pagination__title-h></span><hr></div><div class=pagination__buttons><span class="button next"><a href=/posts/box-is-a-unique-type/><span class=button__text>Box Is a Unique Type</span>
<span class=button__icon></span></a></span></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span>
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>
<script src=/assets/prism.js></script></div></body></html>

View file

@ -1 +1 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"><url><loc>/posts/box-is-a-unique-type/</loc><lastmod>2022-07-23T00:00:00+00:00</lastmod></url><url><loc>/</loc><lastmod>2022-07-23T00:00:00+00:00</lastmod></url><url><loc>/posts/</loc><lastmod>2022-07-23T00:00:00+00:00</lastmod></url><url><loc>/tags/rust/</loc><lastmod>2022-07-23T00:00:00+00:00</lastmod></url><url><loc>/tags/</loc><lastmod>2022-07-23T00:00:00+00:00</lastmod></url><url><loc>/tags/unsafe-code/</loc><lastmod>2022-07-23T00:00:00+00:00</lastmod></url><url><loc>/categories/</loc></url></urlset> <?xml version="1.0" encoding="utf-8" standalone="yes"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"><url><loc>/posts/item-patterns-and-struct-else/</loc><lastmod>2023-03-17T00:00:00+00:00</lastmod></url><url><loc>/tags/language-design/</loc><lastmod>2023-03-17T00:00:00+00:00</lastmod></url><url><loc>/</loc><lastmod>2023-03-17T00:00:00+00:00</lastmod></url><url><loc>/posts/</loc><lastmod>2023-03-17T00:00:00+00:00</lastmod></url><url><loc>/tags/rust/</loc><lastmod>2023-03-17T00:00:00+00:00</lastmod></url><url><loc>/tags/</loc><lastmod>2023-03-17T00:00:00+00:00</lastmod></url><url><loc>/posts/box-is-a-unique-type/</loc><lastmod>2022-07-23T00:00:00+00:00</lastmod></url><url><loc>/tags/unsafe-code/</loc><lastmod>2022-07-23T00:00:00+00:00</lastmod></url><url><loc>/categories/</loc></url></urlset>

View file

@ -1,3 +1,3 @@
<!doctype html><html lang=en><head><title>Tags :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/tags/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="Tags"><meta property="og:description" content><meta property="og:url" content="/tags/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/tags/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=terms><h1>Tags</h1><ul><li><a class=terms-title href=/tags/rust/>rust (1)</a></li><li><a class=terms-title href=/tags/unsafe-code/>unsafe code (1)</a></li></ul></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span> <!doctype html><html lang=en><head><title>Tags :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/tags/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="Tags"><meta property="og:description" content><meta property="og:url" content="/tags/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/tags/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=terms><h1>Tags</h1><ul><li><a class=terms-title href=/tags/language-design/>language-design (1)</a></li><li><a class=terms-title href=/tags/rust/>rust (2)</a></li><li><a class=terms-title href=/tags/unsafe-code/>unsafe code (1)</a></li></ul></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span>
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script> <span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>
<script src=/assets/prism.js></script></div></body></html> <script src=/assets/prism.js></script></div></body></html>

View file

@ -1 +1 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Tags on nilstriebs blog</title><link>/tags/</link><description>Recent content in Tags on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sat, 23 Jul 2022 00:00:00 +0000</lastBuildDate><atom:link href="/tags/index.xml" rel="self" type="application/rss+xml"/><item><title>rust</title><link>/tags/rust/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/tags/rust/</guid><description/><content/></item><item><title>unsafe code</title><link>/tags/unsafe-code/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/tags/unsafe-code/</guid><description/><content/></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>Tags on nilstriebs blog</title><link>/tags/</link><description>Recent content in Tags on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 17 Mar 2023 00:00:00 +0000</lastBuildDate><atom:link href="/tags/index.xml" rel="self" type="application/rss+xml"/><item><title>language-design</title><link>/tags/language-design/</link><pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate><guid>/tags/language-design/</guid><description/><content/></item><item><title>rust</title><link>/tags/rust/</link><pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate><guid>/tags/rust/</guid><description/><content/></item><item><title>unsafe code</title><link>/tags/unsafe-code/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/tags/unsafe-code/</guid><description/><content/></item></channel></rss>

View file

@ -0,0 +1,5 @@
<!doctype html><html lang=en><head><title>language-design :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/tags/language-design/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="language-design"><meta property="og:description" content><meta property="og:url" content="/tags/language-design/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/tags/language-design/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=posts><div class="post on-list"><h1 class=post-title><a href=/posts/item-patterns-and-struct-else/>Item Patterns And Struct Else</a></h1><div class=post-meta><span class=post-date>2023-03-17</span>
<span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/language-design/>language-design</a>&nbsp;</span><div class=post-content>Bringing more expressiveness to our items</div><div><a class="read-more button" href=/posts/item-patterns-and-struct-else/></a></div></div><div class=pagination><div class=pagination__buttons></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span>
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>
<script src=/assets/prism.js></script></div></body></html>

View file

@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>language-design on nilstriebs blog</title><link>/tags/language-design/</link><description>Recent content in language-design on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 17 Mar 2023 00:00:00 +0000</lastBuildDate><atom:link href="/tags/language-design/index.xml" rel="self" type="application/rss+xml"/><item><title>Item Patterns And Struct Else</title><link>/posts/item-patterns-and-struct-else/</link><pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate><guid>/posts/item-patterns-and-struct-else/</guid><description>Pattern matching One of my favourite features of Rust is pattern matching. It&amp;rsquo;s a simple and elegant way to deal with not just structs, but also enums!
enum ItemKind { Struct(String, Vec&amp;lt;Field&amp;gt;), Function(String, Body), } impl ItemKind { fn name(&amp;amp;self) -&amp;gt; &amp;amp;str { match self { Self::Struct(name, _) =&amp;gt; name, Self::Function(name, _) =&amp;gt; name, } } } Here, we have an enum and a function to get the name out of this.</description><content>&lt;h1 id="pattern-matching">Pattern matching&lt;/h1>
&lt;p>One of my favourite features of Rust is pattern matching. It&amp;rsquo;s a simple and elegant way to deal with not just structs, but also enums!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#a6e22e">ItemKind&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Struct(String, Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>Field&lt;span style="color:#f92672">&amp;gt;&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Function(String, Body),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> ItemKind {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">name&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self) -&amp;gt; &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">match&lt;/span> self {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Self::Struct(name, _) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> name,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Self::Function(name, _) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> name,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we have an enum and a function to get the name out of this. In C, this would be very unsafe, as we cannot be guaranteed that our union has the right tag.
But in Rust, the compiler nicely checks it all for us. It&amp;rsquo;s safe and expressive (just like many other features of Rust).&lt;/p>
&lt;p>But that isn&amp;rsquo;t the only way to use pattern matching. While branching is one of its core features (in that sense, pattern matching is just like git),
it doesn&amp;rsquo;t always have to be used. Another major advantage of pattern matching lies in the ability to &lt;em>exhaustively&lt;/em> (not be be confused with exhausting, like writing down brilliant ideas like this) match over inputs.&lt;/p>
&lt;p>Let&amp;rsquo;s look at the following example. Here, we have a struct representing a struct in a programming language. It has a name and fields.
We then manually implement a custom hash trait for it because we are important and need a custom hash trait. We could have written a derive macro, but didn&amp;rsquo;t because
we don&amp;rsquo;t understand how proc macros work.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields: Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>Field&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> HandRolledHash &lt;span style="color:#66d9ef">for&lt;/span> Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self, hasher: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mut&lt;/span> HandRolledHasher) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self.name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self.fields);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This works perfectly. But then later, &lt;a href="https://github.com/rust-lang/rustup/pull/1642">we add privacy to the language&lt;/a>. Now, all types have a visibility.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-diff" data-lang="diff">&lt;span style="display:flex;">&lt;span>struct Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">+ visibility: Vis,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">&lt;/span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields: Vec&amp;lt;Field&amp;gt;,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Pretty cool. Now no one can access the implementation details and make everything a mess. But wait - we have just made a mess! We didn&amp;rsquo;t hash the visibility!
Hashing something incorrectly &lt;a href="https://github.com/rust-lang/rust/issues/84970">doesn&amp;rsquo;t sound too bad&lt;/a>, but it would be nice if this was prevented.&lt;/p>
&lt;p>Thanks to exhaustive pattern matching, it would have been easy to prevent. We just change our hash implementation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> HandRolledHash &lt;span style="color:#66d9ef">for&lt;/span> Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self, hasher: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mut&lt;/span> HandRolledHasher) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">let&lt;/span> Self { name, fields } &lt;span style="color:#f92672">=&lt;/span> self;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(fields);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And with this, adding the visibility will cause a compiler error and alert us that we need to handle it in hashing.
(The decision whether we actually do want to handle it is still up to us. We could also just turn off the computer and make new friends outside.)&lt;/p>
&lt;p>We can conclude that pattern matching is a great feature.&lt;/p>
&lt;h1 id="limitations-of-pattern-matching">Limitations of pattern matching&lt;/h1>
&lt;p>But there is one big limitation of pattern matching - all of its occurrences (&lt;code>match&lt;/code>, &lt;code>if let&lt;/code>, &lt;code>if let&lt;/code> chains, &lt;code>while let&lt;/code>, &lt;code>while let&lt;/code> chains, &lt;code>for&lt;/code>, &lt;code>let&lt;/code>, &lt;code>let else&lt;/code>, and function parameters
(we do have a lot of pattern matching)) are inside of bodies, mostly as part of expressions or statements.&lt;/p>
&lt;p>This doesn&amp;rsquo;t sound too bad. This is where the executed code resides. But it comes at a cost of consistency. We often add many syntactical niceties to expressions and statements, but forget about items.&lt;/p>
&lt;h1 id="items-and-sadness">Items and sadness&lt;/h1>
&lt;p>Items have a hard life. They are the parents of everything important. &lt;code>struct&lt;/code>, &lt;code>enum&lt;/code>, &lt;code>const&lt;/code>, &lt;code>mod&lt;/code>, &lt;code>fn&lt;/code>, &lt;code>union&lt;/code>, &lt;code>global_asm&lt;/code> are all things we use daily, yet their grammar is very limited. (&amp;ldquo;free the items&amp;rdquo; was an alternative blog post title, although &amp;ldquo;freeing&amp;rdquo; generally remains a concern of &lt;a href="https://nilstrieb.github.io/nilstrieb-c-style-guide-edition-2/">my C style guide&lt;/a>).&lt;/p>
&lt;p>For example, see the following code where we declare a few constants.&lt;/p>
&lt;pre tabindex="0">&lt;code>const ONE: u8 = 1;
const TWO: u8 = 1;
const THREE: u8 = 3;
&lt;/code>&lt;/pre>&lt;p>There is nothing obviously wrong with this code. You understand it, I understand it, an ALGOL 68 developer from 1970 would probably understand it
and even an ancient greek philosopher might have a clue (which is impressive, given that they are all not alive anymore). But this is the kind of code that pages you at 4 AM.&lt;/p>
&lt;p>You&amp;rsquo;ve read the last paragraph in confusion. Of course there&amp;rsquo;s something wrong with this code! &lt;code>TWO&lt;/code> is &lt;code>1&lt;/code>, yet the name strongly suggests that it should be &lt;code>2&lt;/code>. And you&amp;rsquo;d
be right, this was just a check to make sure you&amp;rsquo;re still here. You are very clever and deserve this post. If you didn&amp;rsquo;t notice it, go to sleep. It&amp;rsquo;s good for your health.&lt;/p>
&lt;p>But even if it was &lt;code>2&lt;/code>, this code is still not good. There is way too much duplication! &lt;code>const&lt;/code> is mentioned three times. This is a major distraction to the reader.&lt;/p>
&lt;p>Let&amp;rsquo;s have a harder example:&lt;/p>
&lt;pre tabindex="0">&lt;code>const ONE: u8 = 0; const
NAME: &amp;amp;
str = &amp;#34;nils&amp;#34;;
const X: &amp;amp;str
= &amp;#34;const&amp;#34;;const A: () = ();
&lt;/code>&lt;/pre>&lt;p>Here, the &lt;code>const&lt;/code> being noise is a lot more obvious. Did you see that &lt;code>X&lt;/code> contains &lt;code>&amp;quot;const&amp;quot;&lt;/code>? Maybe you did, maybe you didn&amp;rsquo;t. When I tested it, 0/0 people could see it.&lt;/p>
&lt;p>Now imagine if it looked like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> (&lt;span style="color:#66d9ef">ONE&lt;/span>, &lt;span style="color:#66d9ef">NAME&lt;/span>, X, A): (&lt;span style="color:#66d9ef">u8&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span>, ()) &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;nils&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;const&amp;#34;&lt;/span>, ());
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Everything is way shorter and more readable.&lt;/p>
&lt;p>What you&amp;rsquo;ve just seen is a limited form of pattern matching!&lt;/p>
&lt;h1 id="lets-go-further">Let&amp;rsquo;s go further&lt;/h1>
&lt;p>The idea of generalizing pattern matching is very powerful. We can apply this to more than just consts.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> (Person, Car) &lt;span style="color:#f92672">=&lt;/span> ({ name: String }, { wheels: &lt;span style="color:#66d9ef">u8&lt;/span> });
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we create two structs with just a single &lt;code>struct&lt;/code> keyword. This makes it way simpler and easier to read when related structs are declared.
So far we&amp;rsquo;ve just used tuples. But we can go even further. Structs of structs!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Household&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>T, U&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent: &lt;span style="color:#a6e22e">T&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> child: &lt;span style="color:#a6e22e">U&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Household&lt;/span> { parent: &lt;span style="color:#a6e22e">Ferris&lt;/span>, child: &lt;span style="color:#a6e22e">Corro&lt;/span> } &lt;span style="color:#f92672">=&lt;/span> Household {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent: { name: String },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> child: { name: String, unsafety: &lt;span style="color:#66d9ef">bool&lt;/span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we can nicely match on the &lt;code>Household&lt;/code> struct containing the definition of the &lt;code>Ferris&lt;/code> and &lt;code>Corro&lt;/code> structs. This is equivalent to the following code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Feris&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Corro&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> unsafety: &lt;span style="color:#66d9ef">bool&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is already really neat, but there&amp;rsquo;s more. We also have to consider the falliblity of patterns.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> Some(A) &lt;span style="color:#f92672">=&lt;/span> None;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This pattern doesn&amp;rsquo;t match. Inside bodies, we could use an &lt;code>if let&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">let&lt;/span> Some(a) &lt;span style="color:#f92672">=&lt;/span> None {} &lt;span style="color:#66d9ef">else&lt;/span> {}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can also apply this to items.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> Some(A) &lt;span style="color:#f92672">=&lt;/span> None {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/* other items where A exists */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/* other items where A doesn&amp;#39;t exist */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This doesn&amp;rsquo;t sound too useful, but it allows for extreme flexibility!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>macro_rules&lt;span style="color:#f92672">!&lt;/span> are_same_type {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (&lt;span style="color:#75715e">$a&lt;/span>:&lt;span style="color:#a6e22e">ty&lt;/span>, &lt;span style="color:#75715e">$b&lt;/span>:&lt;span style="color:#a6e22e">ty&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">mut&lt;/span> &lt;span style="color:#66d9ef">ARE_SAME&lt;/span>: &lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#75715e">$a&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#75715e">$b&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> _: () &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">unsafe&lt;/span> { &lt;span style="color:#66d9ef">ARE_SAME&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>; };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">unsafe&lt;/span> { &lt;span style="color:#66d9ef">ARE_SAME&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> are_same_type!(Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>String&lt;span style="color:#f92672">&amp;gt;&lt;/span>, String) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> println!(&lt;span style="color:#e6db74">&amp;#34;impossible to reach!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ignoring this suspicious assignment to a &lt;code>static mut&lt;/code>, this is lovely!&lt;/p>
&lt;p>We can go further.&lt;/p>
&lt;p>Today, items are just there with no ordering. What if we imposed an ordering? (and just like this, the C11 atomic model was born.) What if &amp;ldquo;Rust items&amp;rdquo; was a meta scripting language?&lt;/p>
&lt;p>We can write a simple guessing game!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">fn&lt;/span> input() -&amp;gt; &lt;span style="color:#66d9ef">u8&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span>: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span> &lt;span style="color:#f92672">=&lt;/span> prompt!();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> Ok(&lt;span style="color:#66d9ef">INPUT&lt;/span>): Result&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">u8&lt;/span>, ParseIntErr&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span>.parse() &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_error!(&lt;span style="color:#e6db74">&amp;#34;Invalid input&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">INPUT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span>: &lt;span style="color:#66d9ef">u8&lt;/span> &lt;span style="color:#f92672">=&lt;/span> env!(&lt;span style="color:#e6db74">&amp;#34;RANDOM&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">loop&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">=&lt;/span> input();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>; &lt;span style="color:#75715e">// continue compilation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_warn!(&lt;span style="color:#e6db74">&amp;#34;input is smaller&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_warn!(&lt;span style="color:#e6db74">&amp;#34;input is bigger&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Empty. I am useless. I strike!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If it weren&amp;rsquo;t for &lt;code>fn main&lt;/code> starting a strike and stopping compilation, this would have worked! Quite bold of &lt;code>fn main&lt;/code> to just start a strike, even though there&amp;rsquo;s no &lt;code>union&lt;/code> in the entire program. But we really need it, it&amp;rsquo;s not a disposable worker.&lt;/p>
&lt;p>And then, last and least I want to highlight one of my favourite consequences of this: &lt;code>struct else&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> Some(Test) &lt;span style="color:#f92672">=&lt;/span> None &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_error!(&lt;span style="color:#e6db74">&amp;#34;didn&amp;#39;t match pattern&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;!-- raw HTML omitted -->you&amp;rsquo;re asking yourself what you just read. meanwhile, i am asking myself what i just wrote. we are very similar.&lt;!-- raw HTML omitted -->&lt;/p></content></item></channel></rss>

View file

@ -0,0 +1 @@
<!doctype html><html lang=en-us><head><title>/tags/language-design/</title><link rel=canonical href=/tags/language-design/><meta name=robots content="noindex"><meta charset=utf-8><meta http-equiv=refresh content="0; url=/tags/language-design/"></head></html>

View file

@ -1,4 +1,6 @@
<!doctype html><html lang=en><head><title>rust :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/tags/rust/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="rust"><meta property="og:description" content><meta property="og:url" content="/tags/rust/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/tags/rust/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=posts><div class="post on-list"><h1 class=post-title><a href=/posts/box-is-a-unique-type/>Box Is a Unique Type</a></h1><div class=post-meta><span class=post-date>2022-07-23</span> <!doctype html><html lang=en><head><title>rust :: nilstriebs blog</title><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=description content><meta name=keywords content><meta name=robots content="noodp"><link rel=canonical href=/tags/rust/><link rel=stylesheet href=/assets/style.css><link rel=apple-touch-icon href=/img/apple-touch-icon-192x192.png><link rel="shortcut icon" href=/img/favicon/orange.png><meta name=twitter:card content="summary"><meta property="og:locale" content="en"><meta property="og:type" content="website"><meta property="og:title" content="rust"><meta property="og:description" content><meta property="og:url" content="/tags/rust/"><meta property="og:site_name" content="nilstriebs blog"><meta property="og:image" content="/img/favicon/orange.png"><meta property="og:image:width" content="2048"><meta property="og:image:height" content="1024"><link href=/tags/rust/index.xml rel=alternate type=application/rss+xml title="nilstriebs blog"></head><body class=orange><div class="container center headings--one-size"><header class=header><div class=header__inner><div class=header__logo><a href=/><div class=logo>nilstriebs blog</div></a></div></div></header><div class=content><div class=posts><div class="post on-list"><h1 class=post-title><a href=/posts/item-patterns-and-struct-else/>Item Patterns And Struct Else</a></h1><div class=post-meta><span class=post-date>2023-03-17</span>
<span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/language-design/>language-design</a>&nbsp;</span><div class=post-content>Bringing more expressiveness to our items</div><div><a class="read-more button" href=/posts/item-patterns-and-struct-else/></a></div></div><div class="post on-list"><h1 class=post-title><a href=/posts/box-is-a-unique-type/>Box Is a Unique Type</a></h1><div class=post-meta><span class=post-date>2022-07-23</span>
<span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp; <span class=post-author>:: Nilstrieb</span></div><span class=post-tags>#<a href=/tags/rust/>rust</a>&nbsp;
#<a href=/tags/unsafe-code/>unsafe code</a>&nbsp;</span><div class=post-content>About better aliasing semantics for <code>Box&lt;T></code></div><div><a class="read-more button" href=/posts/box-is-a-unique-type/></a></div></div><div class=pagination><div class=pagination__buttons></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span> #<a href=/tags/unsafe-code/>unsafe code</a>&nbsp;</span><div class=post-content>About better aliasing semantics for <code>Box&lt;T></code></div><div><a class="read-more button" href=/posts/box-is-a-unique-type/></a></div></div><div class=pagination><div class=pagination__buttons></div></div></div></div><footer class=footer><div class=footer__inner><div class=copyright><span>© 2023 Powered by <a href=http://gohugo.io>Hugo</a></span>
<span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script> <span>:: Theme made by <a href=https://twitter.com/panr>panr</a></span></div></div></footer><script src=/assets/main.js></script>

View file

@ -1,4 +1,167 @@
<?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 nilstriebs blog</title><link>/tags/rust/</link><description>Recent content in rust on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Sat, 23 Jul 2022 00:00:00 +0000</lastBuildDate><atom:link href="/tags/rust/index.xml" rel="self" type="application/rss+xml"/><item><title>Box Is a Unique Type</title><link>/posts/box-is-a-unique-type/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/posts/box-is-a-unique-type/</guid><description>We have all used Box&amp;lt;T&amp;gt; before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics and flexibility. We can use it to put our values on the heap, but it can do even more than that! <?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 nilstriebs blog</title><link>/tags/rust/</link><description>Recent content in rust on nilstriebs blog</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><lastBuildDate>Fri, 17 Mar 2023 00:00:00 +0000</lastBuildDate><atom:link href="/tags/rust/index.xml" rel="self" type="application/rss+xml"/><item><title>Item Patterns And Struct Else</title><link>/posts/item-patterns-and-struct-else/</link><pubDate>Fri, 17 Mar 2023 00:00:00 +0000</pubDate><guid>/posts/item-patterns-and-struct-else/</guid><description>Pattern matching One of my favourite features of Rust is pattern matching. It&amp;rsquo;s a simple and elegant way to deal with not just structs, but also enums!
enum ItemKind { Struct(String, Vec&amp;lt;Field&amp;gt;), Function(String, Body), } impl ItemKind { fn name(&amp;amp;self) -&amp;gt; &amp;amp;str { match self { Self::Struct(name, _) =&amp;gt; name, Self::Function(name, _) =&amp;gt; name, } } } Here, we have an enum and a function to get the name out of this.</description><content>&lt;h1 id="pattern-matching">Pattern matching&lt;/h1>
&lt;p>One of my favourite features of Rust is pattern matching. It&amp;rsquo;s a simple and elegant way to deal with not just structs, but also enums!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#a6e22e">ItemKind&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Struct(String, Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>Field&lt;span style="color:#f92672">&amp;gt;&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Function(String, Body),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> ItemKind {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">name&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self) -&amp;gt; &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">match&lt;/span> self {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Self::Struct(name, _) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> name,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Self::Function(name, _) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> name,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we have an enum and a function to get the name out of this. In C, this would be very unsafe, as we cannot be guaranteed that our union has the right tag.
But in Rust, the compiler nicely checks it all for us. It&amp;rsquo;s safe and expressive (just like many other features of Rust).&lt;/p>
&lt;p>But that isn&amp;rsquo;t the only way to use pattern matching. While branching is one of its core features (in that sense, pattern matching is just like git),
it doesn&amp;rsquo;t always have to be used. Another major advantage of pattern matching lies in the ability to &lt;em>exhaustively&lt;/em> (not be be confused with exhausting, like writing down brilliant ideas like this) match over inputs.&lt;/p>
&lt;p>Let&amp;rsquo;s look at the following example. Here, we have a struct representing a struct in a programming language. It has a name and fields.
We then manually implement a custom hash trait for it because we are important and need a custom hash trait. We could have written a derive macro, but didn&amp;rsquo;t because
we don&amp;rsquo;t understand how proc macros work.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields: Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>Field&lt;span style="color:#f92672">&amp;gt;&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> HandRolledHash &lt;span style="color:#66d9ef">for&lt;/span> Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self, hasher: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mut&lt;/span> HandRolledHasher) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self.name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self.fields);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This works perfectly. But then later, &lt;a href="https://github.com/rust-lang/rustup/pull/1642">we add privacy to the language&lt;/a>. Now, all types have a visibility.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-diff" data-lang="diff">&lt;span style="display:flex;">&lt;span>struct Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">+ visibility: Vis,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#a6e22e">&lt;/span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> fields: Vec&amp;lt;Field&amp;gt;,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Pretty cool. Now no one can access the implementation details and make everything a mess. But wait - we have just made a mess! We didn&amp;rsquo;t hash the visibility!
Hashing something incorrectly &lt;a href="https://github.com/rust-lang/rust/issues/84970">doesn&amp;rsquo;t sound too bad&lt;/a>, but it would be nice if this was prevented.&lt;/p>
&lt;p>Thanks to exhaustive pattern matching, it would have been easy to prevent. We just change our hash implementation:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">impl&lt;/span> HandRolledHash &lt;span style="color:#66d9ef">for&lt;/span> Struct {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>self, hasher: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#a6e22e">mut&lt;/span> HandRolledHasher) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">let&lt;/span> Self { name, fields } &lt;span style="color:#f92672">=&lt;/span> self;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> hasher.hash(fields);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>And with this, adding the visibility will cause a compiler error and alert us that we need to handle it in hashing.
(The decision whether we actually do want to handle it is still up to us. We could also just turn off the computer and make new friends outside.)&lt;/p>
&lt;p>We can conclude that pattern matching is a great feature.&lt;/p>
&lt;h1 id="limitations-of-pattern-matching">Limitations of pattern matching&lt;/h1>
&lt;p>But there is one big limitation of pattern matching - all of its occurrences (&lt;code>match&lt;/code>, &lt;code>if let&lt;/code>, &lt;code>if let&lt;/code> chains, &lt;code>while let&lt;/code>, &lt;code>while let&lt;/code> chains, &lt;code>for&lt;/code>, &lt;code>let&lt;/code>, &lt;code>let else&lt;/code>, and function parameters
(we do have a lot of pattern matching)) are inside of bodies, mostly as part of expressions or statements.&lt;/p>
&lt;p>This doesn&amp;rsquo;t sound too bad. This is where the executed code resides. But it comes at a cost of consistency. We often add many syntactical niceties to expressions and statements, but forget about items.&lt;/p>
&lt;h1 id="items-and-sadness">Items and sadness&lt;/h1>
&lt;p>Items have a hard life. They are the parents of everything important. &lt;code>struct&lt;/code>, &lt;code>enum&lt;/code>, &lt;code>const&lt;/code>, &lt;code>mod&lt;/code>, &lt;code>fn&lt;/code>, &lt;code>union&lt;/code>, &lt;code>global_asm&lt;/code> are all things we use daily, yet their grammar is very limited. (&amp;ldquo;free the items&amp;rdquo; was an alternative blog post title, although &amp;ldquo;freeing&amp;rdquo; generally remains a concern of &lt;a href="https://nilstrieb.github.io/nilstrieb-c-style-guide-edition-2/">my C style guide&lt;/a>).&lt;/p>
&lt;p>For example, see the following code where we declare a few constants.&lt;/p>
&lt;pre tabindex="0">&lt;code>const ONE: u8 = 1;
const TWO: u8 = 1;
const THREE: u8 = 3;
&lt;/code>&lt;/pre>&lt;p>There is nothing obviously wrong with this code. You understand it, I understand it, an ALGOL 68 developer from 1970 would probably understand it
and even an ancient greek philosopher might have a clue (which is impressive, given that they are all not alive anymore). But this is the kind of code that pages you at 4 AM.&lt;/p>
&lt;p>You&amp;rsquo;ve read the last paragraph in confusion. Of course there&amp;rsquo;s something wrong with this code! &lt;code>TWO&lt;/code> is &lt;code>1&lt;/code>, yet the name strongly suggests that it should be &lt;code>2&lt;/code>. And you&amp;rsquo;d
be right, this was just a check to make sure you&amp;rsquo;re still here. You are very clever and deserve this post. If you didn&amp;rsquo;t notice it, go to sleep. It&amp;rsquo;s good for your health.&lt;/p>
&lt;p>But even if it was &lt;code>2&lt;/code>, this code is still not good. There is way too much duplication! &lt;code>const&lt;/code> is mentioned three times. This is a major distraction to the reader.&lt;/p>
&lt;p>Let&amp;rsquo;s have a harder example:&lt;/p>
&lt;pre tabindex="0">&lt;code>const ONE: u8 = 0; const
NAME: &amp;amp;
str = &amp;#34;nils&amp;#34;;
const X: &amp;amp;str
= &amp;#34;const&amp;#34;;const A: () = ();
&lt;/code>&lt;/pre>&lt;p>Here, the &lt;code>const&lt;/code> being noise is a lot more obvious. Did you see that &lt;code>X&lt;/code> contains &lt;code>&amp;quot;const&amp;quot;&lt;/code>? Maybe you did, maybe you didn&amp;rsquo;t. When I tested it, 0/0 people could see it.&lt;/p>
&lt;p>Now imagine if it looked like this:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> (&lt;span style="color:#66d9ef">ONE&lt;/span>, &lt;span style="color:#66d9ef">NAME&lt;/span>, X, A): (&lt;span style="color:#66d9ef">u8&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span>, ()) &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;nils&amp;#34;&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;const&amp;#34;&lt;/span>, ());
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Everything is way shorter and more readable.&lt;/p>
&lt;p>What you&amp;rsquo;ve just seen is a limited form of pattern matching!&lt;/p>
&lt;h1 id="lets-go-further">Let&amp;rsquo;s go further&lt;/h1>
&lt;p>The idea of generalizing pattern matching is very powerful. We can apply this to more than just consts.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> (Person, Car) &lt;span style="color:#f92672">=&lt;/span> ({ name: String }, { wheels: &lt;span style="color:#66d9ef">u8&lt;/span> });
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Here, we create two structs with just a single &lt;code>struct&lt;/code> keyword. This makes it way simpler and easier to read when related structs are declared.
So far we&amp;rsquo;ve just used tuples. But we can go even further. Structs of structs!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Household&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>T, U&lt;span style="color:#f92672">&amp;gt;&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent: &lt;span style="color:#a6e22e">T&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> child: &lt;span style="color:#a6e22e">U&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Household&lt;/span> { parent: &lt;span style="color:#a6e22e">Ferris&lt;/span>, child: &lt;span style="color:#a6e22e">Corro&lt;/span> } &lt;span style="color:#f92672">=&lt;/span> Household {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> parent: { name: String },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> child: { name: String, unsafety: &lt;span style="color:#66d9ef">bool&lt;/span> },
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Now we can nicely match on the &lt;code>Household&lt;/code> struct containing the definition of the &lt;code>Ferris&lt;/code> and &lt;code>Corro&lt;/code> structs. This is equivalent to the following code:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Feris&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Corro&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name: String,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> unsafety: &lt;span style="color:#66d9ef">bool&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This is already really neat, but there&amp;rsquo;s more. We also have to consider the falliblity of patterns.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> Some(A) &lt;span style="color:#f92672">=&lt;/span> None;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This pattern doesn&amp;rsquo;t match. Inside bodies, we could use an &lt;code>if let&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">let&lt;/span> Some(a) &lt;span style="color:#f92672">=&lt;/span> None {} &lt;span style="color:#66d9ef">else&lt;/span> {}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can also apply this to items.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> Some(A) &lt;span style="color:#f92672">=&lt;/span> None {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/* other items where A exists */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/* other items where A doesn&amp;#39;t exist */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>This doesn&amp;rsquo;t sound too useful, but it allows for extreme flexibility!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>macro_rules&lt;span style="color:#f92672">!&lt;/span> are_same_type {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> (&lt;span style="color:#75715e">$a&lt;/span>:&lt;span style="color:#a6e22e">ty&lt;/span>, &lt;span style="color:#75715e">$b&lt;/span>:&lt;span style="color:#a6e22e">ty&lt;/span>) &lt;span style="color:#f92672">=&amp;gt;&lt;/span> {{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">mut&lt;/span> &lt;span style="color:#66d9ef">ARE_SAME&lt;/span>: &lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">false&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#75715e">$a&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#75715e">$b&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> _: () &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">unsafe&lt;/span> { &lt;span style="color:#66d9ef">ARE_SAME&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">true&lt;/span>; };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">unsafe&lt;/span> { &lt;span style="color:#66d9ef">ARE_SAME&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> are_same_type!(Vec&lt;span style="color:#f92672">&amp;lt;&lt;/span>String&lt;span style="color:#f92672">&amp;gt;&lt;/span>, String) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> println!(&lt;span style="color:#e6db74">&amp;#34;impossible to reach!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Ignoring this suspicious assignment to a &lt;code>static mut&lt;/code>, this is lovely!&lt;/p>
&lt;p>We can go further.&lt;/p>
&lt;p>Today, items are just there with no ordering. What if we imposed an ordering? (and just like this, the C11 atomic model was born.) What if &amp;ldquo;Rust items&amp;rdquo; was a meta scripting language?&lt;/p>
&lt;p>We can write a simple guessing game!&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">fn&lt;/span> input() -&amp;gt; &lt;span style="color:#66d9ef">u8&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span>: &lt;span style="color:#66d9ef">&amp;amp;&lt;/span>&lt;span style="color:#66d9ef">str&lt;/span> &lt;span style="color:#f92672">=&lt;/span> prompt!();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> Ok(&lt;span style="color:#66d9ef">INPUT&lt;/span>): Result&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">u8&lt;/span>, ParseIntErr&lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span>.parse() &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_error!(&lt;span style="color:#e6db74">&amp;#34;Invalid input&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">INPUT&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span>: &lt;span style="color:#66d9ef">u8&lt;/span> &lt;span style="color:#f92672">=&lt;/span> env!(&lt;span style="color:#e6db74">&amp;#34;RANDOM&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">loop&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">=&lt;/span> input();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">break&lt;/span>; &lt;span style="color:#75715e">// continue compilation
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> } &lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> &lt;span style="color:#66d9ef">INPUT&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">RANDOM&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_warn!(&lt;span style="color:#e6db74">&amp;#34;input is smaller&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> } &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_warn!(&lt;span style="color:#e6db74">&amp;#34;input is bigger&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">fn&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// Empty. I am useless. I strike!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If it weren&amp;rsquo;t for &lt;code>fn main&lt;/code> starting a strike and stopping compilation, this would have worked! Quite bold of &lt;code>fn main&lt;/code> to just start a strike, even though there&amp;rsquo;s no &lt;code>union&lt;/code> in the entire program. But we really need it, it&amp;rsquo;s not a disposable worker.&lt;/p>
&lt;p>And then, last and least I want to highlight one of my favourite consequences of this: &lt;code>struct else&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-rust" data-lang="rust">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> Some(Test) &lt;span style="color:#f92672">=&lt;/span> None &lt;span style="color:#66d9ef">else&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> compile_error!(&lt;span style="color:#e6db74">&amp;#34;didn&amp;#39;t match pattern&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;!-- raw HTML omitted -->you&amp;rsquo;re asking yourself what you just read. meanwhile, i am asking myself what i just wrote. we are very similar.&lt;!-- raw HTML omitted -->&lt;/p></content></item><item><title>Box Is a Unique Type</title><link>/posts/box-is-a-unique-type/</link><pubDate>Sat, 23 Jul 2022 00:00:00 +0000</pubDate><guid>/posts/box-is-a-unique-type/</guid><description>We have all used Box&amp;lt;T&amp;gt; before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics and flexibility. We can use it to put our values on the heap, but it can do even more than that!
struct Fields { a: String, b: String, } let fields = Box::new(Fields { a: &amp;#34;a&amp;#34;.to_string(), b: &amp;#34;b&amp;#34;.to_string() }); let a = fields.a; let b = fields.b; This kind of partial deref move is just one of the spectacular magic tricks box has up its sleeve, and they exist for good reason: They are very useful.</description><content>&lt;p>We have all used &lt;code>Box&amp;lt;T&amp;gt;&lt;/code> before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics struct Fields { a: String, b: String, } let fields = Box::new(Fields { a: &amp;#34;a&amp;#34;.to_string(), b: &amp;#34;b&amp;#34;.to_string() }); let a = fields.a; let b = fields.b; This kind of partial deref move is just one of the spectacular magic tricks box has up its sleeve, and they exist for good reason: They are very useful.</description><content>&lt;p>We have all used &lt;code>Box&amp;lt;T&amp;gt;&lt;/code> before in our Rust code. It&amp;rsquo;s a glorious type, with great ergonomics
and flexibility. We can use it to put our values on the heap, but it can do even more and flexibility. We can use it to put our values on the heap, but it can do even more
than that!&lt;/p> than that!&lt;/p>