<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Matthias Endler</title>
    <subtitle>Consultant at corrode.dev. Likes just-in-time compilers and hot chocolate</subtitle>
    <link rel="self" type="application/atom+xml" href="https://endler.dev/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://endler.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-01-26T00:00:00+00:00</updated>
    <id>https://endler.dev/atom.xml</id>
    <entry xml:lang="en">
        <title>Now&#x27;s The Time To Start That Blog</title>
        <published>2026-01-26T00:00:00+00:00</published>
        <updated>2026-01-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2026/personal-blog/"/>
        <id>https://endler.dev/2026/personal-blog/</id>
        
        <content type="html" xml:base="https://endler.dev/2026/personal-blog/">&lt;p&gt;I was listening to a podcast recently where someone pointed out something curious: machines have been better at playing chess than humans for three decades now, and nobody cares.
People still watch human chess players.
If anything, chess is experiencing a renaissance.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t know anyone who wants to watch robots play chess.
But I know plenty of people who love watching humans play.
I’m not a big chess player myself (heck, I could hardly win any game), but I catch myself watching matches on YouTube.&lt;&#x2F;p&gt;
&lt;p&gt;The reason is that the game is way more than moving pieces on a board.
There’s a background story to every player and the match is a truly human experience where people don’t only compete against an opponent but also against themselves.
That’s what makes it so interesting, not the fact that there’s an algorithm which has 3646 Elo.
Humans can still contribute!&lt;&#x2F;p&gt;
&lt;p&gt;And I think it’s the same with writing.&lt;&#x2F;p&gt;
&lt;p&gt;Everyone wants to read personal thoughts from real human beings, but no one writes them anymore.
What we get instead is slop, and that’s hardly a good read.
The moment I notice I’m reading autogenerated text, I care less.&lt;&#x2F;p&gt;
&lt;p&gt;That’s why I keep writing.
My personal blog is a weird mix of ramblings about &lt;a href=&quot;&#x2F;2025&#x2F;how-to-review-code&#x2F;&quot;&gt;reviewing code&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;2025&#x2F;best-programmers&#x2F;&quot;&gt;the best programmers I know&lt;&#x2F;a&gt;, and random thoughts.&lt;&#x2F;p&gt;
&lt;p&gt;But you know what? People are reading it and from time to time I get an email from someone who found one of my articles helpful.&lt;&#x2F;p&gt;
&lt;p&gt;Time and again, when I talk to friends, they share the same experience.
My friend Thomas wrote his first article about his &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;thomaszahner.ch&#x2F;posts&#x2F;atlassian-experience&#x2F;&quot;&gt;Experience with Atlassian&lt;&#x2F;a&gt; and many people found it helpful and reached out.
And even if no one does, writing is a joyful hobby and it helps me clear my thoughts.&lt;&#x2F;p&gt;
&lt;p&gt;I believe there has rarely been a better time to start writing.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Building Up And Sanding Down</title>
        <published>2025-10-31T00:00:00+00:00</published>
        <updated>2025-10-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2025/building-up-and-sanding-down/"/>
        <id>https://endler.dev/2025/building-up-and-sanding-down/</id>
        
        <content type="html" xml:base="https://endler.dev/2025/building-up-and-sanding-down/">&lt;p&gt;Over the years, I’ve gravitated toward two complementary ways to build robust software systems: building up and sanding down.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Building up&lt;&#x2F;strong&gt; means starting with a tiny core and gradually adding functionality.
&lt;strong&gt;Sanding down&lt;&#x2F;strong&gt; means starting with a very rough idea and refining it over time.&lt;&#x2F;p&gt;
&lt;p&gt;Neither approach is inherently better; it’s almost a stylistic decision that depends on team dynamics and familiarity with the problem domain.
On top of that, my thoughts on the topic are not particularly novel, but I wanted to summarize what I’ve learned over the years.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-up&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#building-up&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Building Up&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2025&amp;#x2F;building-up-and-sanding-down&amp;#x2F;stonework.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2025&amp;#x2F;building-up-and-sanding-down&amp;#x2F;stonework.jpg&quot; 
        
            alt=&quot;Working on a solid stone block in ancient Egypt&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;500&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Working on a solid stone block in ancient Egypt
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:%C3%84gypten_Steinbearbeitung.png&quot;&gt;Wikimedia&lt;&#x2F;a&gt; Public Domain
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Building up focuses on creating a solid foundation first.
I like to use it when working on systems I know well or when there is a clear specification I can refer to.
For example, I use it for implementing protocols or when emulating hardware such as for my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;mos6502&quot;&gt;MOS 6502 emulator&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I prefer “building up” over “bottom-up” as the former evokes construction and upward growth. “Bottom-up” is more abstract and directional.
Also “bottom-up” always felt like jargon while “building up” is more intuitive and very visual, so it could help communicate the idea to non-technical stakeholders.&lt;&#x2F;p&gt;
&lt;p&gt;There are a few rules I try to follow when building up:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Focus on atomic building blocks that are easily composable and testable.&lt;&#x2F;li&gt;
&lt;li&gt;Build up powerful guarantees from simple, verifiable properties.&lt;&#x2F;li&gt;
&lt;li&gt;Focus on correctness, not performance.&lt;&#x2F;li&gt;
&lt;li&gt;Write the documentation along with the code to test your reasoning.&lt;&#x2F;li&gt;
&lt;li&gt;Nail the abstractions before moving on to the next layer.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;When I collaborate with highly analytical people, this approach works well.
People who have a background in formal methods or mathematics tend to think in terms of “building blocks” and proofs.
I also found that functional programmers tend to prefer this approach.&lt;&#x2F;p&gt;
&lt;p&gt;In languages like Rust, the type system can help enforce invariants and make it easier to build up complex systems from simple components.
Also, Rust’s trait system encourages composition, which aligns well with that line of thinking.&lt;&#x2F;p&gt;
&lt;p&gt;The downside of the “build up” approach is that you end up spending a lot of time on the foundational layers before you can see any tangible results.
It can be slow to get to an MVP this way.
Some people also find this approach too rigid and inflexible, as it can be hard to pivot or change direction once you’ve committed to a certain architecture.&lt;&#x2F;p&gt;
&lt;p&gt;For example, say you’re building a web framework.
There are a ton of questions at the beginning of the project:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Will it be synchronous or asynchronous?&lt;&#x2F;li&gt;
&lt;li&gt;How will the request routing work?&lt;&#x2F;li&gt;
&lt;li&gt;Will there be middleware? How?&lt;&#x2F;li&gt;
&lt;li&gt;How will the response generation work?&lt;&#x2F;li&gt;
&lt;li&gt;How will error handling be done?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In a building-up approach, you would start by answering these questions and designing the core abstractions first.
Foundational components like the request and response types, the router, and the middleware system are the backbone of the framework and have to be rock solid.&lt;&#x2F;p&gt;
&lt;p&gt;Only after you’ve pinned down the core data structures and their interactions would you move on to building the public API.
This can lead to a very robust and well-designed system, but it can also take a long time to get there.&lt;&#x2F;p&gt;
&lt;p&gt;For instance, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;http&#x2F;latest&#x2F;src&#x2F;http&#x2F;request.rs.html#158&quot;&gt;here&lt;&#x2F;a&gt; is the &lt;code&gt;Request&lt;&#x2F;code&gt; struct from the popular &lt;code&gt;http&lt;&#x2F;code&gt; crate:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;derive&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Request&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    head&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Parts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Component parts of an HTTP `Request`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The HTTP request head consists of a method, uri, version, and a set of&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; header fields.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;derive&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Parts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The request&amp;#39;s method&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; method&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Method&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The request&amp;#39;s URI&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; uri&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Uri&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The request&amp;#39;s version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; version&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Version&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The request&amp;#39;s headers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; headers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; HeaderMap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;HeaderValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; The request&amp;#39;s extensions&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; extensions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Extensions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    _priv&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are quite a few clever design decisions in this short piece of code:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;Request&lt;&#x2F;code&gt; struct is generic over the body type &lt;code&gt;T&lt;&#x2F;code&gt;, allowing for flexibility in how the body is represented (e.g., as a byte stream, a string, etc.).&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;Parts&lt;&#x2F;code&gt; struct is separated from the &lt;code&gt;Request&lt;&#x2F;code&gt; struct, allowing for easy access to the request metadata without needing to deal with the body.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;Extensions&lt;&#x2F;code&gt; can be used to store extra data derived from the underlying protocol.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;_priv: ()&lt;&#x2F;code&gt; field is a zero-sized type used to prevent external code from constructing &lt;code&gt;Parts&lt;&#x2F;code&gt; directly. It enforces the use of the provided constructors and ensures that the invariants of the &lt;code&gt;Parts&lt;&#x2F;code&gt; struct are maintained.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;With the exception of extensions, this design has stood the test of time.
It has remained largely unchanged since the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hyperium&#x2F;http&#x2F;commit&#x2F;0858e716984c95d2dd0c04f57a228e324ebc0f41&quot;&gt;very first version&lt;&#x2F;a&gt; in 2017.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sanding-down&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#sanding-down&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Sanding Down&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2025&amp;#x2F;building-up-and-sanding-down&amp;#x2F;Rekhmire-tomb-drawing-furniture.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2025&amp;#x2F;building-up-and-sanding-down&amp;#x2F;Rekhmire-tomb-drawing-furniture.jpg&quot; 
        
            alt=&quot;Drawing of the part of wall painting in the tomb of Rekhmire&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;314&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Drawing of the part of wall painting in the tomb of Rekhmire
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Rekhmire-tomb-drawing-furniture.jpg&quot;&gt;Wikimedia&lt;&#x2F;a&gt; Public Domain
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The alternative approach, which I found to work equally well, is “sanding down.”
In this approach, you start with a rough prototype (or vertical slice) and refine it over time.
You “sand down” the rough edges over and over again, until you are happy with the result.
It feels a bit like woodworking, where you start with a rough piece of wood and gradually refine it into a work of art.
(Not that I have any idea what woodworking is like, but I imagine it’s something like that.)&lt;&#x2F;p&gt;
&lt;p&gt;Crucially, this is similar but not identical to prototyping.
The difference is that you don’t plan on throwing away the code you write.
Instead, you’re trying to exploit the iterative nature of the problem and purposefully work on “drafts” until you get to the final version.
At any point in time you can stop and ship the current version if needed.&lt;&#x2F;p&gt;
&lt;p&gt;I find that this approach works well when working on creative projects which require experimentation and quick iteration.
People with a background in game development or scripting languages tend to prefer this approach, as they are used to working in a more exploratory way.&lt;&#x2F;p&gt;
&lt;p&gt;When using this approach, I try to follow these rules:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Switch off your inner perfectionist.&lt;&#x2F;li&gt;
&lt;li&gt;Don’t edit while writing the first draft.&lt;&#x2F;li&gt;
&lt;li&gt;Code duplication is strictly allowed.&lt;&#x2F;li&gt;
&lt;li&gt;Refactor, refactor, refactor.&lt;&#x2F;li&gt;
&lt;li&gt;Defer testing until after the first draft is done.&lt;&#x2F;li&gt;
&lt;li&gt;Focus on the outermost API first; nail that, then polish the internals.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This approach makes it easy to throw code away and try something new.
I found that it can be frustrating for people who like to plan ahead and are very organized and methodical.
The “chaos” seems to be off-putting for some people.&lt;&#x2F;p&gt;
&lt;p&gt;As an example, say you’re writing a game in Rust.
You might want to tweak all aspects of the game and quickly iterate on the gameplay mechanics until they feel “just right.”&lt;&#x2F;p&gt;
&lt;p&gt;In order to do so, you might start with a skeleton of the game loop and nothing else.
Then you add a player character that can move around the screen.
You tweak the jump height and movement speed until it &lt;em&gt;feels good&lt;&#x2F;em&gt;.
There is very little abstraction between you and the game logic at this point.
You might have a lot of duplicated code and hardcoded values, but that’s okay for now.
Once the core gameplay mechanics are pinned down, you can start refactoring the code.&lt;&#x2F;p&gt;
&lt;p&gt;I think Rust can get in the way if you use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bevy.org&#x2F;&quot;&gt;Bevy&lt;&#x2F;a&gt; or other frameworks early on in the game design process.
The entity component system can feel quite heavy and hinder rapid iteration.
(At least that’s how I felt when I tried Bevy last time.)&lt;&#x2F;p&gt;
&lt;p&gt;I had a much better experience creating my own window and rendering loop using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;macroquad.rs&#x2F;&quot;&gt;macroquad&lt;&#x2F;a&gt;.
Yes, the entire code was in one file and no, there were no tests.
There also wasn’t any architecture to speak of.&lt;&#x2F;p&gt;
&lt;p&gt;And yet… working on the game felt amazing!
I knew that I could always refactor the code later, but I wanted to stay in the moment and get the gameplay right first.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;red&#x2F;blob&#x2F;4d798f88d2b9de18619c875bff6d5c75f4a4dcc3&#x2F;src&#x2F;main.rs#L285C1-L304C2&quot;&gt;my game loop&lt;&#x2F;a&gt;, which was extremely imperative and didn’t require learning a big framework to get started:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;macroquad&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Game&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; input_handler&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; InputHandler&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    clear_background&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;BLACK&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Get inputs - only once per frame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; input_handler&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get_movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; action&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; input_handler&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get_action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Update player with both movement and action inputs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;update&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;movement&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get_frame_time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Draw&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;draw&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        next_frame&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;await&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You don’t have to be a Rust expert to understand this code.&lt;&#x2F;p&gt;
&lt;p&gt;In every loop iteration, I simply:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;get the inputs&lt;&#x2F;li&gt;
&lt;li&gt;update the player state&lt;&#x2F;li&gt;
&lt;li&gt;draw the player&lt;&#x2F;li&gt;
&lt;li&gt;wait for the next frame&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It’s a very typical design for that type of work.&lt;&#x2F;p&gt;
&lt;p&gt;If I wanted to, I could now sand down the code and refactor it into a more modular design until it’s production-ready.
I could introduce a “listener&#x2F;callback” system to separate input handling from player logic or a scene graph to manage multiple game objects or an ontology system to manage game entities and their components.
But why bother?
For now, I care about the game mechanics, not the architecture.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finding-the-right-balance&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#finding-the-right-balance&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Finding the Right Balance&lt;&#x2F;h2&gt;
&lt;p&gt;Both variants can lead to correct, maintainable, and efficient systems.
There is no better or worse approach.&lt;&#x2F;p&gt;
&lt;p&gt;I found that most people gravitate toward one approach or the other.
However, it helps to be familiar with both approaches and know when to apply which mode.
Choose wisely, because switching between the two approaches is quite tricky as you start from different ends of the problem.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>On Choosing Rust</title>
        <published>2025-09-26T00:00:00+00:00</published>
        <updated>2025-09-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2025/choosing-rust/"/>
        <id>https://endler.dev/2025/choosing-rust/</id>
        
        <content type="html" xml:base="https://endler.dev/2025/choosing-rust/">&lt;p&gt;Since my professional writing on Rust has moved to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&quot;&gt;corrode blog&lt;&#x2F;a&gt;, I can be a bit more casual on here and share some of my personal thoughts on the recent debate around using Rust in established software.&lt;&#x2F;p&gt;
&lt;p&gt;The two projects in question are git (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lore.kernel.org&#x2F;git&#x2F;20250904-b4-pks-rust-breaking-change-v1-0-3af1d25e0be9@pks.im&#x2F;&quot;&gt;kernel thread&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=45312696&quot;&gt;Hacker News Discussion&lt;&#x2F;a&gt;) and the recently rewritten &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;uutils&#x2F;coreutils&quot;&gt;coreutils in Rust&lt;&#x2F;a&gt;, which will &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;discourse.ubuntu.com&#x2F;t&#x2F;carefully-but-purposefully-oxidising-ubuntu&#x2F;56995&quot;&gt;ship with Ubuntu 25.10 Quizzical Quokka&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;What prompted me to write this post is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;x.com&#x2F;nafonsopt&#x2F;status&#x2F;1968954376262652175&quot;&gt;discussion on Twitter&lt;&#x2F;a&gt; and a blog post titled &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dayvster.com&#x2F;blog&#x2F;are-we-chasing-language-hype-over-solving-real-problems&quot;&gt;“Are We Chasing Language Hype Over Solving Real Problems?”&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In both cases, the authors speculate about the motivations behind choosing Rust, and as someone who helps teams use Rust in production, I find those takes… hilarious.&lt;&#x2F;p&gt;
&lt;p&gt;Back when I started corrode, people always mentioned that Rust wasn’t used for anything serious.
I knew about the production use cases from client work, but there was very little public information out there.
As a consequence, we started the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;podcast&#x2F;&quot;&gt;‘Rust in Production’&lt;&#x2F;a&gt; podcast to show that companies indeed choose Rust for real-world applications.
However, people don’t like to be proven wrong, so that conspiracy theory has now morphed into “Big Rust” trying to take over the world. 😆&lt;&#x2F;p&gt;
&lt;p&gt;Let’s look at some of the claims made in the blog post and Twitter thread and see how these could be debunked pretty easily.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“GNU Core Utils has basically never had any major security vulnerabilities in its entire existence”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If only that were true.
A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cve.org&#x2F;CVERecord&#x2F;SearchResults?query=coreutils&quot;&gt;quick CVE search&lt;&#x2F;a&gt; shows multiple security issues over the decades, including buffer overflows and path traversal vulnerabilities. Just a few months ago, a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nvd.nist.gov&#x2F;vuln&#x2F;detail&#x2F;CVE-2025-5278&quot;&gt;heap buffer under-read&lt;&#x2F;a&gt; was found in &lt;code&gt;sort&lt;&#x2F;code&gt;, which would cause a leak of sensitive data if an attacker sends a specially crafted input stream.&lt;&#x2F;p&gt;
&lt;p&gt;The GNU coreutils are one of the most widely used software packages worldwide with billions of installations and hundreds (thousands?) of developers looking at the code.
Yes, vulnerabilities still happen.
No, it is not easy to write correct, secure C code.
No, not even if you’re extra careful and disciplined.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;ls&lt;&#x2F;code&gt; is five thousand lines long. (Check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coreutils&#x2F;coreutils&#x2F;blob&#x2F;master&#x2F;src&#x2F;ls.c&quot;&gt;source code&lt;&#x2F;a&gt;). That’s a lot of code for printing file names and metadata and a big attack surface!&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Rust can only ever match C performance at best and is usually slower”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Work by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;trifectatech.org&#x2F;initiatives&#x2F;codegen&#x2F;&quot;&gt;Trifecta&lt;&#x2F;a&gt; shows that it is possible to write Rust code that is faster than C in some cases.
Especially in concurrent workloads and with memory safety guarantees.
If writing safe C code is too hard, try writing safe concurrent C code!&lt;&#x2F;p&gt;
&lt;p&gt;That’s where Rust shines.
You can achieve ridiculous levels of parallelization without worrying about security issues.
And no, you don’t need to litter your code with &lt;code&gt;unsafe&lt;&#x2F;code&gt; blocks.
Check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=q8qn0dyT3xc&quot;&gt;Steve Klabnik’s recent talk about Oxide&lt;&#x2F;a&gt; where he shows that their bootloader and their preemptive multitasking OS, hubris – both pretty core systems code – only contain 5% of &lt;code&gt;unsafe&lt;&#x2F;code&gt; code each.
You can write large codebases in Rust with no unsafe code at all.&lt;&#x2F;p&gt;
&lt;p&gt;As a trivial example, I sat down to rewrite &lt;code&gt;cat&lt;&#x2F;code&gt; in Rust one day.
The result was 3x faster than GNU &lt;code&gt;cat&lt;&#x2F;code&gt; on my machine.
You can read the &lt;a href=&quot;&#x2F;2018&#x2F;fastcat&#x2F;&quot;&gt;post here&lt;&#x2F;a&gt;.
All I did was use &lt;code&gt;splice&lt;&#x2F;code&gt; to copy data, which saves one memory copy.
Performance is not only dependent on the language but on the algorithms and system calls you use.&lt;&#x2F;p&gt;
&lt;p&gt;If you play into Rust’s strengths, you can match C’s performance.
At least there is no technical limitation that would prevent this.
And I personally feel more willing to aggressively optimize my code in Rust, because I don’t have to worry about introducing memory safety bugs.
It feels like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;steveklabnik.com&#x2F;writing&#x2F;is-rust-faster-than-c&#x2F;&quot;&gt;I’m not alone&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We reward novelty over necessity in the industry”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This ignores that most successful companies (Google, Meta, etc.) primarily use battle-tested tech stacks, not bleeding-edge languages.
These companies have massive codebases and cannot afford to rewrite everything in the latest trendy language.
But they see the value of using Rust for new components and gradually rewriting existing ones.
That’s because &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;why-rust&#x2F;#reasons-for-using-rust-in-production&quot;&gt;70% of security vulnerabilities are memory safety issues&lt;&#x2F;a&gt; and these issues are extremely costly to fix.
If these companies could avoid switching to a new language to do so, they would.&lt;&#x2F;p&gt;
&lt;p&gt;Besides, Rust is not exactly &lt;em&gt;new&lt;&#x2F;em&gt; anymore.
Rust 1.0 was released 10+ years ago!
The industry is moving slowly, but not that slowly.
You’d be surprised to find out how many established companies use Rust without even announcing it or thinking of it as “novelty”.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“100% orchestrated”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Multiple people in the Twitter thread were convinced this is some coordinated master plan rather than developers choosing better tools,
while the very maintainers of git and coreutils openly discussed their motivations in public forums for everyone to see.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“They’re trying to replace&#x2F;erase C. It’s not going to happen”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;They are right. C is not going away anytime soon.
There is just so much C&#x2F;C++ code out there in the wild, and rewriting everything in Rust is not feasible.
The good news is that you can incrementally rewrite C&#x2F;C++ code in Rust, one component at a time.
That’s what the git maintainers are planning, by using Rust for new components.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“They’re rewriting software with a GNU license into software with an MIT license”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Even if you use Rust, you can still license your code under GPL or any other license you want.
Git itself remains GPL, and many Rust projects use various licenses, not only MIT.
The license fear is often brought up by people who don’t understand how open source licensing works or it might just be FUD.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;interoperable-europe.ec.europa.eu&#x2F;licence&#x2F;compatibility-check&#x2F;GPL-2.0%20&#x2F;MIT&quot;&gt;MIT code is still compatible with GPL code&lt;&#x2F;a&gt; and you can use both of them in the same project without issues.
It’s just that the end product (the thing you deliver to your users, i.e. binary executables) is now covered by GPL because of its virality.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“It’s just developers being bored and wanting to work with shiny new languages”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The aging maintainers of C projects are retiring, and there are fewer new developers willing to pick up C just to maintain legacy code in their free time.
C developers are essentially going extinct.
New developers want to work with modern languages and who can blame them?
Or would you want to maintain a 40-year-old COBOL codebase or an old Perl script?
We have to move on.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Why not build something completely new instead of rewriting existing tools?”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;It’s not that easy.
The code is only part of the story.
The other part is the ecosystem, the tooling, the integrations, the documentation, and the user base.
All of that takes years to build.
Users don’t want to change their workflows, so they want drop-in replacements.
Proven interfaces and APIs, no matter how crude and old-fashioned, have a lot of value.&lt;&#x2F;p&gt;
&lt;p&gt;But yes, new tools are being built in Rust as well.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“They don’t know how to actually solve problems, just chase trends”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Talk about dismissing the technical expertise of maintainers who’ve been working on these projects for years or decades and understand the pain points better than anyone.&lt;&#x2F;p&gt;
&lt;p&gt;If they were just chasing trends, they wouldn’t be maintaining these projects in the first place!
These people are some of the most experienced developers in the world, and yet people want to tell them how to do their jobs.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“It’s part of the woke mind virus infecting software”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Imagine thinking memory safety is a political conspiracy.
Apparently preventing buffer overflows is now an ideological stance.
The closest thing to this is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bidenwhitehouse.archives.gov&#x2F;oncd&#x2F;briefing-room&#x2F;2024&#x2F;02&#x2F;26&#x2F;press-release-technical-report&#x2F;&quot;&gt;White House’s technical report&lt;&#x2F;a&gt; which recommends memory-safe languages for government software and mandating memory safety for software receiving federal funding is a pretty reasonable take.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#conclusion&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I could go on, but I think you get my point.&lt;&#x2F;p&gt;
&lt;p&gt;People who give Rust an honest chance know that it offers advantages in terms of memory safety, concurrency, and maintainability.
It’s not about chasing hype but about long-term investment in software quality.
As more companies successfully adopt Rust every day, it increasingly becomes the default choice for many new projects.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re interested in learning more about using Rust in production, check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&quot;&gt;my other blog&lt;&#x2F;a&gt; or listen to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;podcast&#x2F;&quot;&gt;Rust in Production podcast&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, and if you know someone who posts such takes, stop arguing and send them a link to this post.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How To Review Code</title>
        <published>2025-08-06T00:00:00+00:00</published>
        <updated>2025-08-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2025/how-to-review-code/"/>
        <id>https://endler.dev/2025/how-to-review-code/</id>
        
        <content type="html" xml:base="https://endler.dev/2025/how-to-review-code/">&lt;p&gt;I’ve been reviewing other people’s code for a while now, more than two decades to be precise.
Nowadays, I spend around 50-70% of my time reviewing code in some form or another.
It’s what I get paid to do, alongside systems design.&lt;&#x2F;p&gt;
&lt;p&gt;Over time, I learned a thing or two about how to review code effectively.
I focus on different things now than when I started.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;think-about-the-big-picture&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#think-about-the-big-picture&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Think About The Big Picture&lt;&#x2F;h2&gt;
&lt;p&gt;Bad reviews are narrow in scope.
They focus on syntax, style, and minor issues instead of maintainability and extensibility.&lt;&#x2F;p&gt;
&lt;p&gt;Good reviews look at not only the changes, but also what problems the changes solve, what future issues might arise, and how a change fits into the overall design of the system.&lt;&#x2F;p&gt;
&lt;p&gt;I like to look at the lines that &lt;em&gt;weren’t&lt;&#x2F;em&gt; changed. They often tell the true story.&lt;&#x2F;p&gt;
&lt;p&gt;For example, often people forget to update a related section of the codebase or the docs.
This can lead to bugs, confusion, breaking changes, or security issues.&lt;&#x2F;p&gt;
&lt;p&gt;Be thorough and look at all call-sites of the new code.
Have they been correctly updated?
Are the tests still testing the right thing?
Are the changes in the right place?&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;Here’s a cheat sheet of questions I ask myself when reviewing code:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;How does this code fit into the rest of the system?&lt;&#x2F;li&gt;
&lt;li&gt;What’s its interaction with other parts of the codebase?&lt;&#x2F;li&gt;
&lt;li&gt;How does it affect the overall architecture?&lt;&#x2F;li&gt;
&lt;li&gt;Does it impact future planned work?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;These questions have more to do with systems design than with the changes themselves.
Don’t neglect the bigger picture because systems become brittle if you accept bad changes.&lt;&#x2F;p&gt;
&lt;p&gt;Code isn’t written in isolation.
The role of more experienced developers is to reduce operational friction and handle risk management for the project.
The documentation, the tests, and the data types are equally as important as the code itself.&lt;&#x2F;p&gt;
&lt;p&gt;Always keep an eye out for better abstractions as the code evolves.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;naming-is-everything&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#naming-is-everything&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Naming Is Everything&lt;&#x2F;h2&gt;
&lt;p&gt;I spend a big chunk of my time thinking about good names when reviewing code.&lt;&#x2F;p&gt;
&lt;p&gt;Naming things is hard, which is why it’s so important to get it right.
Often, it’s the most important part of a code review.&lt;&#x2F;p&gt;
&lt;p&gt;It’s also the most subjective part, which makes it tedious because it’s hard to distinguish between nitpicking and important naming decisions.&lt;&#x2F;p&gt;
&lt;p&gt;Names encapsulate concepts and serve as “building blocks” in your code.
Bad names are the code smell that hint at problems running deep.
They increase cognitive overhead by one or more orders of magnitude.&lt;&#x2F;p&gt;
&lt;p&gt;For example, say we have a struct that represents a player’s stats in a game:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Player&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    username&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    score&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I often see code like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Bad: using temporary&#x2F;arbitrary names creates confusion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; update_player_stats&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Player&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bonus_points&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; level_up&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Player&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; usr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;username&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;trim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_lowercase&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; updated_score&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;score &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bonus_points&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; level_up&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;level &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;level &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Player&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        username&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; usr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        score&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; updated_score&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; l2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code is hard to read and understand.
What is &lt;code&gt;usr&lt;&#x2F;code&gt;, &lt;code&gt;updated_score&lt;&#x2F;code&gt;, and &lt;code&gt;l2&lt;&#x2F;code&gt;? The purpose is not conveyed clearly.
This builds up cognitive load and make it harder to follow the logic.&lt;&#x2F;p&gt;
&lt;p&gt;That’s why I always think of the most fitting names for variables, even if it feels like I’m being pedantic.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Good: meaningful names that describe the transformation at each step&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; update_player_stats&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Player&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bonus_points&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; i32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; level_up&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Player&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Each variable name describes what the value represents&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; username&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;username&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;trim&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_lowercase&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; score&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;score &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bonus_points&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Use shadowed variables to clarify intent&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; level_up&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;level &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; player&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;level &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; level&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; level&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; If done correctly, the final variable names&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; often match the struct&amp;#39;s field names&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Player&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        username&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        score&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        level&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Good names become even more critical in larger codebases where values are declared far away from where they’re used
and where many developers have to have a shared understanding of the problem domain.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-be-afraid-to-say-no&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#don-t-be-afraid-to-say-no&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Don’t Be Afraid To Say “No”&lt;&#x2F;h2&gt;
&lt;p&gt;I have to decline changes all the time and it’s never easy.
After all someone put in a lot of effort and they want to see their work accepted.&lt;&#x2F;p&gt;
&lt;p&gt;Avoid sugarcoating your decision or trying to be nice.
Be objective, explain your reasoning and provide better alternatives.
Don’t dwell on it, but focus on the next steps.&lt;&#x2F;p&gt;
&lt;p&gt;It’s better to say no than to accept something that isn’t right and will cause problems down the road.
In the future it will get even harder to deny a change once you’ve set a precedent.&lt;&#x2F;p&gt;
&lt;p&gt;That’s the purpose of the review process: there is no guarantee that the code will be accepted.&lt;&#x2F;p&gt;
&lt;p&gt;In open source, many people will contribute code that doesn’t meet your standards.
There needs to be someone who says “no” and this is a very unpopular job (ask any open source maintainer).
However, great projects need gatekeepers because the alternative is subpar code and eventually unmaintainable projects.&lt;&#x2F;p&gt;
&lt;p&gt;At times, people will say “let’s just merge this and fix it later.”
I think that’s a slippery slope.
It can lead to tech debt and additional work later on.
It’s hard to stand your ground, but it’s important to do so.
If you see something that isn’t right, speak up.&lt;&#x2F;p&gt;
&lt;p&gt;When it gets hard, remember that you’re not rejecting the person, you’re rejecting the code.
Remind people that you appreciate their effort and that you want to help them improve.&lt;&#x2F;p&gt;
&lt;p&gt;Even though you’ll develop an intuition for what to focus on in reviews, you should still back it up with facts.
If you find yourself saying “no” to the same thing over and over again, consider writing a style guide or a set of guidelines for your team.&lt;&#x2F;p&gt;
&lt;p&gt;Be gracious but decisive; it’s just code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code-review-is-communication&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#code-review-is-communication&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Code Review Is Communication&lt;&#x2F;h2&gt;
&lt;p&gt;Code reviews aren’t just about code; people matter too.
Building a good relationship with your coworkers is important.&lt;&#x2F;p&gt;
&lt;p&gt;I make it a point to do the first couple of reviews together in a pair programming session if possible.&lt;&#x2F;p&gt;
&lt;p&gt;This way, you can learn from each other’s communication style.
Building trust and getting to know each other works well this way.
You should repeat that process later if you notice a communication breakdown or misunderstanding.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;use-multiple-iterations-of-reviews&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#use-multiple-iterations-of-reviews&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Use Multiple Iterations Of Reviews&lt;&#x2F;h2&gt;
&lt;p&gt;“Can you take a quick look at this PR? I want to merge it today.”
There often is an expectation that code reviews are a one-time thing.
That’s not how it works.
Instead, code reviews are an iterative process.
Multiple iterations should be expected to get the code right.&lt;&#x2F;p&gt;
&lt;p&gt;In my first iteration, I focus on the big picture and the overall design.
Once I’m done with that, I go into the details.&lt;&#x2F;p&gt;
&lt;p&gt;The goal shouldn’t be to merge as quickly as possible, but to accept code that is of high quality.
Otherwise, what’s the point of a code review in the first place?
That’s a mindset shift that’s important to make.&lt;&#x2F;p&gt;
&lt;p&gt;Reviews aren’t &lt;em&gt;exclusively&lt;&#x2F;em&gt; about pointing out flaws, they’re also about creating a shared understanding of the code within the team.
I often learn the most about writing better code by reviewing other people’s code.
I’ve also gotten excellent feedback on my own code from excellent engineers.&lt;&#x2F;p&gt;
&lt;p&gt;These are invaluable “aha moments” that help you grow as a developer.
Experts spent their valuable time reviewing &lt;em&gt;my&lt;&#x2F;em&gt; code, and I learned a lot from it.
I think everybody should experience that once in their career.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-be-a-jerk&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#don-t-be-a-jerk&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Don’t Be A Jerk&lt;&#x2F;h2&gt;
&lt;p&gt;From time to time, you’ll disagree with the author.
Being respectful and constructive is important.
Avoid personal attacks or condescending language.
Don’t say “this is wrong.”
Instead, say “I would do it this way.”
If people are hesitant, ask a few questions to understand their reasoning.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;“Will this break existing workflows if we do it this way?”&lt;&#x2F;li&gt;
&lt;li&gt;“Which alternatives have you considered?”&lt;&#x2F;li&gt;
&lt;li&gt;“What happens if you call this function with an empty array?”&lt;&#x2F;li&gt;
&lt;li&gt;“If I don’t set this value, what will be the error message presented to the user?”&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Socratic_questioning&quot;&gt;“Socratic questions”&lt;&#x2F;a&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-lucca-1&quot;&gt;&lt;a href=&quot;#fn-lucca&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; help the author think about their decisions and can lead to better designs.&lt;&#x2F;p&gt;
&lt;p&gt;People should enjoy receiving your feedback.
If not, revisit your review style.
Only add comments that you yourself would be happy to receive.&lt;&#x2F;p&gt;
&lt;p&gt;From time to time, I like to add positive comments like “I like this” or “this is a great idea.”
Keeping the author motivated and showing that you appreciate their work goes a long way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;if-possible-try-to-run-the-code&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#if-possible-try-to-run-the-code&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;If Possible, Try To Run The Code&lt;&#x2F;h2&gt;
&lt;p&gt;It’s easy to miss subtle details when you look at code for too long.
Having a local copy of the code that I can play with helps me a lot.&lt;&#x2F;p&gt;
&lt;p&gt;I try to run the code, the tests, and the linters if I can.
Checking out the branch, moving things around, breaking things, and trying to understand how it works is part of my review process.&lt;&#x2F;p&gt;
&lt;p&gt;User-facing changes like UI changes or error messages are often easier to spot when you run the code and try to break it.&lt;&#x2F;p&gt;
&lt;p&gt;After that, I revert the changes and, if needed, write down my findings in a comment.
Better understanding can come from this approach.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;be-upfront-about-your-availability&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#be-upfront-about-your-availability&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Be Upfront About Your Availability&lt;&#x2F;h2&gt;
&lt;p&gt;Code reviews are often a bottleneck in the development process, because they can’t be fully automated:
there’s a human in the loop who has to look at the code and provide feedback.&lt;&#x2F;p&gt;
&lt;p&gt;But if you wait for your colleagues to review your code, that can lead to frustration.
Avoid being that person.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes you won’t have time to review code and that is okay.
If you can’t review the code in a reasonable time, let the author know.&lt;&#x2F;p&gt;
&lt;p&gt;I’m still working on this, but I try to be more proactive about my availability and set clear expectations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;never-stop-learning&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#never-stop-learning&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Never Stop Learning&lt;&#x2F;h2&gt;
&lt;p&gt;Code reviews are my favorite way to learn new things.
I learn new techniques, patterns, new libraries, but most importantly, how other people approach problems.&lt;&#x2F;p&gt;
&lt;p&gt;I try to learn one new thing with each review.
It’s not wasted time, if it helps the team improve and grow as a whole.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-be-nitpicky&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#don-t-be-nitpicky&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Don’t Be Nitpicky&lt;&#x2F;h2&gt;
&lt;p&gt;Formatters exist for a reason: leave whitespace and formatting to the tools.
Save your energy for issues that truly matter.&lt;&#x2F;p&gt;
&lt;p&gt;Focus on logic, design, maintainability, and correctness. Avoid subjective preferences that don’t impact code quality.&lt;&#x2F;p&gt;
&lt;p&gt;Ask yourself: Does this affect functionality or would it confuse future developers? If not, let it go.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;focus-on-the-why-not-the-how&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#focus-on-the-why-not-the-how&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Focus On The Why, Not The How&lt;&#x2F;h2&gt;
&lt;p&gt;When reviewing code, focus on the reasoning behind the changes.
This has a much better chance of success than pointing out flaws without any reasoning.&lt;&#x2F;p&gt;
&lt;p&gt;Consider the following two code review comments.
The first one is unhelpful and dismissive.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2025&#x2F;how-to-review-code&#x2F;bad-review-comment.png&quot; alt=&quot;A code review comment just saying: “Don’t do this.”&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The second suggests an alternative, links to the documentation, and explains why the change could lead to problems down the road.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2025&#x2F;how-to-review-code&#x2F;good-review-comment.png&quot; alt=&quot;A code review comment explaining the reasoning behind rejecting the change by providing a helpful alternative and a link to the docs&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Which one would you prefer to receive?&lt;&#x2F;p&gt;
&lt;p&gt;I realize that this requires more time and effort, but it’s worth it!
Most of the time, the author will appreciate it and avoid making the same mistake in the future. There is a compound effect from helpful reviews over time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-be-afraid-to-ask-stupid-questions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#don-t-be-afraid-to-ask-stupid-questions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Don’t Be Afraid To Ask Stupid Questions&lt;&#x2F;h2&gt;
&lt;p&gt;Asking is better than assuming.
If you don’t understand something, ask the author to explain it.
Chances are, you’re not the only one who doesn’t get it.&lt;&#x2F;p&gt;
&lt;p&gt;Often, the author will be happy to explain their reasoning.
Better understanding of the code and the system as a whole can result from this.
It can also help the author see things from a different perspective.
Perhaps they’ll learn that their assumptions were wrong or that the system isn’t self-explanatory.
Perhaps there’s missing documentation?&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a href=&quot;&#x2F;2024&#x2F;asking-better-questions&#x2F;&quot;&gt;Asking great questions is a superpower.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ask-for-feedback-on-your-reviewing-style&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#ask-for-feedback-on-your-reviewing-style&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Ask For Feedback On Your Reviewing Style&lt;&#x2F;h2&gt;
&lt;p&gt;From time to time, ask the author for feedback on your feedback:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Have you been too harsh&#x2F;nitpicky&#x2F;slow&#x2F;sloppy?&lt;&#x2F;li&gt;
&lt;li&gt;Did you point out the right things?&lt;&#x2F;li&gt;
&lt;li&gt;Did your feedback help them?&lt;&#x2F;li&gt;
&lt;li&gt;Do they have suggestions for improvement?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Basically, you ask them to review your review process, heh.&lt;&#x2F;p&gt;
&lt;p&gt;Learning how to review code is a skill that needs constant practice and refinement.
Good luck finding your own style.&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-lucca&quot;&gt;
&lt;p&gt;Thanks for pointing out that term to me, Lucca! &lt;a href=&quot;#fr-lucca-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Repeat Yourself</title>
        <published>2025-06-23T00:00:00+00:00</published>
        <updated>2025-07-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2025/repeat-yourself/"/>
        <id>https://endler.dev/2025/repeat-yourself/</id>
        
        <content type="html" xml:base="https://endler.dev/2025/repeat-yourself/">&lt;p&gt;One of the most repeated pieces of advice throughout my career in software has been “don’t repeat yourself,” also known as the DRY principle.
For the longest time, I took that at face value, never questioning its validity.&lt;&#x2F;p&gt;
&lt;p&gt;That was until I saw actual experts write code: &lt;strong&gt;they copy code all the time&lt;&#x2F;strong&gt;&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-experts-1&quot;&gt;&lt;a href=&quot;#fn-experts&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.
I realized that repeating yourself has a few great benefits.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-people-love-dry&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-people-love-dry&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Why People Love DRY&lt;&#x2F;h2&gt;
&lt;p&gt;The common wisdom is that if you repeat yourself, you have to fix the same bug in multiple places, but if you have a shared abstraction, you only have to fix it once.&lt;&#x2F;p&gt;
&lt;p&gt;Another reason why we avoid repetition is that it makes us feel clever.
“Look, I know all of these smart ways to avoid repetition! I know how to use interfaces, generics, higher-order functions, and inheritance!”&lt;&#x2F;p&gt;
&lt;p&gt;Both reasons are misguided.
There are many benefits of repeating yourself that might get us closer to our goals in the long run.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keeping-up-the-momentum&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#keeping-up-the-momentum&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Keeping Up The Momentum&lt;&#x2F;h2&gt;
&lt;p&gt;When you’re writing code, you want to keep the momentum going to get into a flow state.
If you constantly pause to design the perfect abstraction, it’s easy to lose momentum.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, if you allow yourself to copy-paste code, you keep your train of thought going and work on the problem at hand.
You don’t introduce another problem of trying to find the right abstraction at the same time.&lt;&#x2F;p&gt;
&lt;p&gt;It’s often easier to copy existing code and modify it until it becomes too much of a burden, at which point you can go and refactor it.&lt;&#x2F;p&gt;
&lt;p&gt;I would argue that “writing mode” and “refactoring mode” are two different modes of programming.
During writing mode, you want to focus on getting the idea down and stop your inner critic, which keeps telling you that your code sucks.
During refactoring mode, you take the opposite role: that of the critic.
You look for ways to improve the code by finding the right abstractions, removing duplication, and improving readability.&lt;&#x2F;p&gt;
&lt;p&gt;Keep these two modes separate.
Don’t try to do both at the same time.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-1-1&quot;&gt;&lt;a href=&quot;#fn-1&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finding-the-right-abstraction-is-hard&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#finding-the-right-abstraction-is-hard&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Finding The Right Abstraction Is Hard&lt;&#x2F;h2&gt;
&lt;p&gt;When you start to write code, you don’t know the right abstraction just yet.
But if you copy code, the right abstraction reveals itself; it’s too tedious to copy the same code over and over again, at which point you start to look for ways to abstract it away.
For me, this typically happens after the first copy of the same code, but I try to resist the urge until the 2nd or 3rd copy.&lt;&#x2F;p&gt;
&lt;p&gt;If you start too early, you might end up with a bad abstraction that doesn’t fit the problem.
You know it’s wrong because it &lt;em&gt;feels clunky&lt;&#x2F;em&gt;.
Some typical symptoms include:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Generic names that don’t convey intent, e.g., &lt;code&gt;render_pdf_file&lt;&#x2F;code&gt; instead of &lt;code&gt;generate_invoice&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Difficult to understand without additional context&lt;&#x2F;li&gt;
&lt;li&gt;The abstraction is only used in one or two places&lt;&#x2F;li&gt;
&lt;li&gt;Tight coupling to implementation details&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;it-s-hard-to-get-rid-of-wrong-abstractions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#it-s-hard-to-get-rid-of-wrong-abstractions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;It’s Hard To Get Rid Of Wrong Abstractions&lt;&#x2F;h2&gt;
&lt;p&gt;We easily settle for the first abstraction that comes to mind, but most often, it’s not the right one.
And removing the &lt;em&gt;wrong&lt;&#x2F;em&gt; abstraction is hard work, because now the data flow depends on it.&lt;&#x2F;p&gt;
&lt;p&gt;We also tend to fall in love with our own abstractions because they took time and effort to create.
This makes us reluctant to discard them even when they no longer fit the problem—it’s a sunk cost fallacy.&lt;&#x2F;p&gt;
&lt;p&gt;It gets worse when other programmers start to depend on it, too.
Then you have to be careful about changing it, because it might break other parts of the codebase.
Once you introduce an abstraction, you have to work with it for a long time, sometimes forever.&lt;&#x2F;p&gt;
&lt;p&gt;If you had a copy of the code instead, you could just change it in one place without worrying about breaking anything else.&lt;&#x2F;p&gt;
&lt;div&gt;
  &lt;blockquote cite=&quot;https:&#x2F;&#x2F;sandimetz.com&#x2F;blog&#x2F;2016&#x2F;1&#x2F;20&#x2F;the-wrong-abstraction&quot;&gt;
    &lt;p&gt;
      Duplication is far cheaper than the wrong abstraction
    &lt;&#x2F;p&gt;
  &lt;&#x2F;blockquote&gt;
  &lt;p&gt;—Sandi Metz, &lt;cite&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sandimetz.com&#x2F;blog&#x2F;2016&#x2F;1&#x2F;20&#x2F;the-wrong-abstraction&quot;&gt;The Wrong Abstraction&lt;&#x2F;a&gt;&lt;&#x2F;cite&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;Better to wait until the &lt;em&gt;last moment&lt;&#x2F;em&gt; to settle on the abstraction, when you have a solid understanding of the problem space.&lt;sup class=&quot;footnote-reference&quot; id=&quot;fr-ooda-1&quot;&gt;&lt;a href=&quot;#fn-ooda&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-mental-overhead-of-abstractions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-mental-overhead-of-abstractions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Mental Overhead of Abstractions&lt;&#x2F;h2&gt;
&lt;p&gt;Abstraction reduces code duplication, but it comes at a cost.&lt;&#x2F;p&gt;
&lt;p&gt;Abstractions can make code harder to read, understand, and maintain because you have to jump between multiple levels of indirection to understand what the code does.
The abstraction might live in different files, modules, or libraries.&lt;&#x2F;p&gt;
&lt;p&gt;The cost of traversing these layers is high.
An expert programmer might be able to keep a few levels of abstraction in their head, but we all have a limited context window (which depends on familiarity with the codebase).&lt;&#x2F;p&gt;
&lt;p&gt;When you copy code, you can keep all the logic in one place.
You can just read the whole thing and understand what it does.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;resist-the-urge-of-premature-abstraction&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#resist-the-urge-of-premature-abstraction&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Resist The Urge Of Premature Abstraction&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes, code &lt;em&gt;looks&lt;&#x2F;em&gt; similar but serves different purposes.&lt;&#x2F;p&gt;
&lt;p&gt;For example, consider two pieces of code that calculate a sum by iterating over a collection of items.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;total&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; shopping_cart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    total&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;price&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;quantity&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And elsewhere in the code, we have&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;total&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; package_items&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    total&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In both cases, we iterate over a collection and calculate a total.
You might be tempted to introduce a helper function, but the two calculations are very different.&lt;&#x2F;p&gt;
&lt;p&gt;After a few iterations, these two pieces of code might evolve in different directions:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; calculate_total_price&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;shopping_cart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator z-keyword z-operator z-logical z-python&quot;&gt; not&lt;&#x2F;span&gt;&lt;span&gt; shopping_cart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;        raise&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; ValueError&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Shopping cart cannot be empty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    total&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; shopping_cart&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Round for financial precision&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        total&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; round&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;price&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;quantity&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; total&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In contrast, the shipping cost calculation might look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; calculate_shipping_cost&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;package_items&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; destination_zone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Use higher of actual weight vs dimensional weight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    total_weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; package_items&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    total_volume&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; sum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;length&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;width&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;height&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span&gt; item&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; package_items&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    dimensional_weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; total_volume&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5000&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; FedEx formula&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    billable_weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; max&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;total_weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; dimensional_weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; billable_weight&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span&gt; shipping_rates&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;destination_zone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Had we applied “don’t repeat yourself” too early, we would have lost the context and specific requirements of each calculation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dry-can-introduce-complexity&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#dry-can-introduce-complexity&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;DRY Can Introduce Complexity&lt;&#x2F;h2&gt;
&lt;p&gt;The DRY principle is misinterpreted as a blanket rule to avoid any duplication at all costs, which can lead to complexity.&lt;&#x2F;p&gt;
&lt;p&gt;When you try to avoid repetition by introducing abstractions, you have to deal with all the edge cases in a place far away from the actual business logic.
You end up adding redundant checks and conditions to the abstraction, just to make sure it works in all cases.
Later on, you might forget the reasoning behind those checks, but you keep them around “just in case” because you don’t want to break any callers.
The result is dead code that adds complexity to the codebase; all because you wanted to avoid repeating yourself.&lt;&#x2F;p&gt;
&lt;p&gt;The common wisdom is that if you repeat yourself, you have to fix the same bug in multiple places.
But the assumption is that the bug exists in all copies.
In reality, each copy might have evolved in different ways, and the bug might only exist in one of them.&lt;&#x2F;p&gt;
&lt;p&gt;When you create a shared abstraction, a bug in that abstraction breaks &lt;em&gt;every&lt;&#x2F;em&gt; caller, breaking multiple features at once.
With duplicated code, a bug is isolated to just one specific use case.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;clean-up-afterwards&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#clean-up-afterwards&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Clean Up Afterwards&lt;&#x2F;h2&gt;
&lt;p&gt;Knowing that you didn’t break anything in a shared abstraction is much harder than checking a single copy of the code.
Of course, if you have a lot of copies, there is a risk of forgetting to fix all of them.&lt;&#x2F;p&gt;
&lt;p&gt;The key to making this work is to clean up afterwards.
This can happen before you commit the code or during a code review.&lt;&#x2F;p&gt;
&lt;p&gt;At this stage, you can look at the code you copied and see if it makes sense to keep it as is or if you can see the right abstraction.
I try to refactor code once I have a better understanding of the problem, but not earlier.&lt;&#x2F;p&gt;
&lt;p&gt;A trick to undo a bad abstraction is to inline the code back into the places where it was used.
For a while, you end up “repeating yourself” again in the codebase, but that’s okay.
Rethink the problem based on the new information you have.
Often you’ll find a better abstraction that fits the problem better.&lt;&#x2F;p&gt;
&lt;div&gt;
  &lt;blockquote cite=&quot;https:&#x2F;&#x2F;sandimetz.com&#x2F;blog&#x2F;2016&#x2F;1&#x2F;20&#x2F;the-wrong-abstraction&quot;&gt;
    &lt;p&gt;
      When the abstraction is wrong, the fastest way forward is back.
    &lt;&#x2F;p&gt;
  &lt;&#x2F;blockquote&gt;
  &lt;p&gt;—Sandi Metz, &lt;cite&gt;&lt;a href=&quot;https:&#x2F;&#x2F;sandimetz.com&#x2F;blog&#x2F;2016&#x2F;1&#x2F;20&#x2F;the-wrong-abstraction&quot;&gt;The Wrong Abstraction&lt;&#x2F;a&gt;&lt;&#x2F;cite&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;div&gt;
&lt;h2 id=&quot;tl-dr&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#tl-dr&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;tl;dr&lt;&#x2F;h2&gt;
&lt;p&gt;It’s fine to look for the right abstraction, but don’t obsess over it.
Don’t be afraid to copy code when it helps you keep momentum and find the right abstraction.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;It bears repeating: “Repeat yourself.”&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;section class=&quot;footnotes&quot;&gt;
&lt;ol class=&quot;footnotes-list&quot;&gt;
&lt;li id=&quot;fn-experts&quot;&gt;
&lt;p&gt;For some examples, see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ToOt-osLxNk&quot;&gt;Ferris working on Rustendo64&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=j79G5Be8Q4Y&quot;&gt;tokiospliff working on a C++ game engine&lt;&#x2F;a&gt;. &lt;a href=&quot;#fr-experts-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;This is also how I write prose: I first write a draft and block my inner critic, and then I play the role of the editor&#x2F;critic and “refactor” the text.
This way, I get the best of both worlds: a quick feedback loop which doesn’t block my creativity, and a final product which is more polished and well-structured.
Of course, I did not invent this approach. I recommend reading “Shitty first drafts” from Anne Lamott’s book &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;canongate.co.uk&#x2F;books&#x2F;3055-bird-by-bird-instructions-on-writing-and-life&#x2F;&quot;&gt;Bird by Bird: Instructions on Writing and Life&lt;&#x2F;a&gt; if you want to learn more about this technique. &lt;a href=&quot;#fr-1-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li id=&quot;fn-ooda&quot;&gt;
&lt;p&gt;This is similar to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;OODA_loop&quot;&gt;OODA loop&lt;&#x2F;a&gt; concept, which stands for “Observe, Orient, Decide, Act.” It was developed by military strategist John Boyd. Fighter pilots use it to wait until the last responsible moment to decide on a course of action, which allows them to make the best decision based on the current situation and available information. &lt;a href=&quot;#fr-ooda-1&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;section&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Watching Millionaires</title>
        <published>2025-06-06T00:00:00+00:00</published>
        <updated>2025-06-06T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2025/watching-millionaires/"/>
        <id>https://endler.dev/2025/watching-millionaires/</id>
        
        <content type="html" xml:base="https://endler.dev/2025/watching-millionaires/">&lt;p&gt;I watched the Champions League final the other day when it struck me:
&lt;strong&gt;I’m basically watching millionaires all the time.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The players are millionaires, the coaches are millionaires, the club owners are millionaires. It’s surreal.&lt;&#x2F;p&gt;
&lt;p&gt;This week I watched John Wick Ballerina and, again, there’s Keanu Reeves, who is a millionaire, and Ana de Armas, who is as well.&lt;&#x2F;p&gt;
&lt;p&gt;Yesterday I heard about Trump and Musk fighting. They are not millionaires, they are billionaires!&lt;&#x2F;p&gt;
&lt;p&gt;As I’m writing this, I’m watching the Rock am Ring live stream, a music festival in Germany. Weezer is playing. These guys are all millionaires.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t know what to make of it.
It’s a strange realization, but one that feels worth sharing.&lt;&#x2F;p&gt;
&lt;p&gt;I could go down the road of how this fixation on elites distracts us from the people nearby, but that’s not quite it.
What interests me more is how normalized this has become.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe it’s just the power law in action: a few rise to the top, and we amplify them by watching. But most people in every field aren’t millionaires. We just don’t &lt;em&gt;see&lt;&#x2F;em&gt; them.&lt;&#x2F;p&gt;
&lt;p&gt;You’re on a tiny blog by a tiny man and if you made it this far, I appreciate you. It looks as if you care about the little stories as well.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re anything like me, you’re not only enjoying the little stories, you’re actively &lt;em&gt;seeking&lt;&#x2F;em&gt; them out – but there’s so few of it nowadays. Yes, there are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bearblog.dev&#x2F;discover&#x2F;&quot;&gt;still places&lt;&#x2F;a&gt; where people share their stories, but you need to know where to look.&lt;&#x2F;p&gt;
&lt;p&gt;If anything, we all should share more. &lt;a href=&quot;&#x2F;2024&#x2F;what-to-write&#x2F;&quot;&gt;Write about&lt;&#x2F;a&gt; the little things, the everyday moments, the people you meet, the things &lt;em&gt;you&lt;&#x2F;em&gt; care about. Don’t live anybody else’s life!&lt;&#x2F;p&gt;
&lt;p&gt;Rivers Cuomo, Weezer’s lead singer, once wrote:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;My motivation is much different now than it was then: then I was terribly discontent and dreaming of being a classical composer, a writer, or basically &lt;strong&gt;anything that I wasn’t&lt;&#x2F;strong&gt;; now I just want to enjoy my life and do the responsible thing—graduate.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;That’s from his &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.weezerpedia.com&#x2F;wiki&#x2F;Harvard&quot;&gt;Letter For Readmission To Harvard (2005)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Nobody forced him to go back to Harvard after so many years.
He was a freaking millionaire rock star by then.&lt;&#x2F;p&gt;
&lt;p&gt;And yet, he did.&lt;&#x2F;p&gt;
&lt;p&gt;He stopped &lt;em&gt;pretending&lt;&#x2F;em&gt; and started &lt;em&gt;living&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;We don’t have to keep watching other people’s lives.&lt;&#x2F;p&gt;
&lt;p&gt;Live your own.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Paolo the Plumber</title>
        <published>2025-06-02T00:00:00+00:00</published>
        <updated>2025-06-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2025/paolo/"/>
        <id>https://endler.dev/2025/paolo/</id>
        
        <content type="html" xml:base="https://endler.dev/2025/paolo/">&lt;p&gt;Paolo was a plumber.&lt;&#x2F;p&gt;
&lt;p&gt;People knew him as a reliable and thorough craftsman.
He fixed the pipes in his small town and made a good living doing so.&lt;&#x2F;p&gt;
&lt;p&gt;One day, his friend Mario told him that he’d bought a plumbing machine.
Paolo was intrigued and asked how it worked.&lt;&#x2F;p&gt;
&lt;p&gt;“It’s magical!” said Mario.
“I show it what’s broken, and it fixes the problem in no time!”
Paolo asked if he could watch the machine work.&lt;&#x2F;p&gt;
&lt;p&gt;The next day, Paolo and Mario took the machine to a house with a broken pipe.
Paolo watched as Mario positioned the machine by the pipe.
“Beep boop,” and the machine started working, and quickly.
Paolo noticed the machine turned the wrench back and forth instead of steady pressure - something he could adapt for his own work.
Within minutes, the pipe was fixed.&lt;&#x2F;p&gt;
&lt;p&gt;“Soon no one will need plumbers anymore,” said Mario.
“I can already do the work of ten plumbers with this machine!”&lt;&#x2F;p&gt;
&lt;p&gt;That night, Paolo couldn’t sleep.
He thought about his job and how it might change.
He loved being a plumber and helping people.
But what if machines really took over?&lt;&#x2F;p&gt;
&lt;p&gt;Within a few weeks, Paolo’s phone stopped ringing.
People were calling Mario instead because he did quicker, cheaper work.
Some of Paolo’s old customers told him he was “old-fashioned” and “out of touch.”&lt;&#x2F;p&gt;
&lt;p&gt;In the past, none of his customers had ever complained about his work.
He always took time to do things right.
He would check every joint, seal every pipe, and make sure everything was perfect before leaving.
Sometimes he noticed other problems that needed fixing and he would offer to fix those too.&lt;&#x2F;p&gt;
&lt;p&gt;Then one day, he got a call from an old customer.
It was an emergency.
The pipes in the restaurant were leaking and they needed help fast.
Paolo rushed over and found a mess.
He got to work and fixed the problem.&lt;&#x2F;p&gt;
&lt;p&gt;“We just got it fixed the other day!”
When Paolo asked who did the work, the owner said it was Mario.&lt;&#x2F;p&gt;
&lt;p&gt;From that day on, more people called Paolo.
They all had problems after working with Mario and the machine.
Paolo kept finding the same mistakes: pipes not properly sealed, joints not aligned correctly, leaks temporarily fixed with instant glue.
Sometimes the machine would add extra parts: pipes that ended nowhere, valves that didn’t connect to anything.
Paolo recognized these as signs of the machine at work.&lt;&#x2F;p&gt;
&lt;p&gt;Paolo called Mario and told him what he’d found.
Mario knew about the issues: “I told it to fix it, but it didn’t work right. Even when I asked multiple times and was very polite.”
And worse: “One time I looked away for a moment and the machine started remodeling the bathroom! It added a new sink that wasn’t there before.”&lt;&#x2F;p&gt;
&lt;p&gt;Paolo asked why he didn’t just fix it himself.
“I can’t,” Mario said.
“I don’t know how to do it without the machine.”&lt;&#x2F;p&gt;
&lt;p&gt;Mario had been a reputable plumber before he got the machine.
Now he was relying on a machine that didn’t always work.
Worse, Mario didn’t own the machine but rented it from a company far away.
The rent was cheap in the beginning, but now it was getting more expensive.&lt;&#x2F;p&gt;
&lt;p&gt;Paolo realized that Mario wasn’t the only one.
Many plumbers were using machines now, and new plumbers were learning machines instead of tools.
It wasn’t just plumbers—electricians, carpenters, other tradespeople were all relying on machines.
The machines caused problems, but the company promised they would fix everything and get better with time.
They kept updating the machines and gave them fancy names, but the problems remained.&lt;&#x2F;p&gt;
&lt;p&gt;Paolo just kept working.
He fixed what the machines broke.
His customers called him back for more work.
Soon his phone was ringing like before.&lt;&#x2F;p&gt;
&lt;p&gt;A while later, a salesperson came to town with a new machine.
Paolo heard Mario talking to him at the coffee shop.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Reinvent the Wheel</title>
        <published>2025-05-24T00:00:00+00:00</published>
        <updated>2025-05-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2025/reinvent-the-wheel/"/>
        <id>https://endler.dev/2025/reinvent-the-wheel/</id>
        
        <content type="html" xml:base="https://endler.dev/2025/reinvent-the-wheel/">&lt;p&gt;One of the most harmful pieces of advice is to not reinvent the wheel.&lt;&#x2F;p&gt;
&lt;p&gt;It usually comes from a good place, but is typically given by two groups of people:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;those who tried to invent a wheel themselves and know how hard it is&lt;&#x2F;li&gt;
&lt;li&gt;those who never tried to invent a wheel and blindly follow the advice&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Either way, both positions lead to a climate where curiosity and exploration gets discouraged.
I’m glad that some people didn’t follow that advice; we owe them many of the conveniences of modern life.&lt;&#x2F;p&gt;
&lt;p&gt;Even on a surface level, the advice is bad:
We have much better wheels today than 4500–3300 BCE when the first wheel was invented.
It was also &lt;em&gt;crucially&lt;&#x2F;em&gt; important that wheels got reinvented throughout civilizations and cultures.&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Note:&lt;&#x2F;strong&gt; When I say “wheel” throughout this post, please replace it with whatever
tool, protocol, service, technology, or other invention you’re personally interested in.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;inventing-wheels-is-learning&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#inventing-wheels-is-learning&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Inventing Wheels Is Learning&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;“What I cannot create, I do not understand”&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
– &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Richard_Feynman&quot;&gt;Richard Feynman&lt;&#x2F;a&gt;, Physicist and Nobel Prize Winner&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;To &lt;em&gt;really&lt;&#x2F;em&gt; understand something on a fundamental level, you have to be able to implement a toy version first.
It doesn’t matter if it’s any good; you can throw it away later.&lt;&#x2F;p&gt;
&lt;p&gt;In Computer Science, for example, there are many concepts that are commonly assumed to be beyond the abilities of mere mortals:
protocols, cryptography, and web servers come to mind.&lt;&#x2F;p&gt;
&lt;p&gt;More people should know how these things work.
And therefore I think people should not be afraid to recreate them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;everything-is-a-rabbit-hole&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#everything-is-a-rabbit-hole&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Everything Is A Rabbit Hole&lt;&#x2F;h2&gt;
&lt;p&gt;Too often, fundamental things are taken for granted.
For example strings or paths are super complicated concepts in programming.
It’s a great exercise to implement a string or a path library yourself
if you’re interested in how they work.&lt;&#x2F;p&gt;
&lt;p&gt;Even if nobody ends up using your work, I bet you’ll learn a lot. For example:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There is an infinite complexity in everyday things.&lt;&#x2F;li&gt;
&lt;li&gt;Building something that even a single other person finds useful is a humbling experience.&lt;&#x2F;li&gt;
&lt;li&gt;Humans like you created these abstractions. They are not perfect and you can make different tradeoffs in your own design.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;On the last point, everything is a tradeoff and there are dozens, sometimes hundreds of footguns with every toy problem.&lt;&#x2F;p&gt;
&lt;p&gt;Along the way, you will have to make decisions about correctness, simplicity, functionality, scalability, performance, resource usage, portability, and so on.&lt;&#x2F;p&gt;
&lt;p&gt;Your solution can be great in some of these things, but not all of them and not for all users.
That also implies that existing solutions have flaws and might not be designed to solve your particular problem; no matter how well-established the solution is.&lt;&#x2F;p&gt;
&lt;p&gt;Going down rabbit holes is fun in its own way, but there is one other benefit:
It is one of the few ways to level up as an engineer… but only if you don’t give up before you end up with a working version of what you tried to explore.
If you jump between projects too often, you will learn nothing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reasons-for-reinventing-the-wheel&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#reasons-for-reinventing-the-wheel&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Reasons for Reinventing the Wheel&lt;&#x2F;h2&gt;
&lt;p&gt;There are great reasons to reinvent the wheel:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Build a better wheel (for some definition of better)&lt;&#x2F;li&gt;
&lt;li&gt;Learn how wheels are made&lt;&#x2F;li&gt;
&lt;li&gt;Teach others about wheels&lt;&#x2F;li&gt;
&lt;li&gt;Learn about the inventors of wheels&lt;&#x2F;li&gt;
&lt;li&gt;Be able to change wheels or fix them when they break&lt;&#x2F;li&gt;
&lt;li&gt;Learn the tools needed to make wheels along the way&lt;&#x2F;li&gt;
&lt;li&gt;Learn a tiny slice of what it means to build a larger system (such as a vehicle)&lt;&#x2F;li&gt;
&lt;li&gt;Help someone in need of a very special wheel. Maybe for a wheelchair?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Who knows? The wheel you come up with might not be the best use for a car, but maybe for a… skateboard or a bike?
Or you fail building a nicer wheel, but you come up with a better way to test wheels along the way.
Heck, your wheel might not even be meant for transportation at all!
It might be a potter’s wheel, “a machine used in the shaping (known as throwing) of clay into round ceramic ware” &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Wheel&quot;&gt;according to Wikipedia&lt;&#x2F;a&gt;.
You might end up building a totally different kind of wheel like a steering wheel or a flywheel.
We need more people who think outside the box.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reuse-vs-reinvent&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#reuse-vs-reinvent&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Reuse vs Reinvent&lt;&#x2F;h2&gt;
&lt;p&gt;Of course, don’t disregard the works of others – study their work and reuse where you see fit. Don’t reinvent the wheel out of distrust or ignorance of the work of others.
On the other side, if you never tried to put your knowledge to the test, how would you ever learn enough about your field to advance it?&lt;&#x2F;p&gt;
&lt;p&gt;I observed you can move very quickly by running little experiments. Especially in software engineering, building small prototypes is cheap and quick. Solve your own problem, start small, keep it simple, iterate.&lt;&#x2F;p&gt;
&lt;p&gt;So, with all of the above, here’s my advice:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Reinvent for insight. Reuse for impact.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>No Matter What</title>
        <published>2025-04-13T00:00:00+00:00</published>
        <updated>2025-04-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/no-matter-what/"/>
        <id>https://endler.dev/2024/no-matter-what/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/no-matter-what/">&lt;p&gt;As kids, our parents established a few simple rules that we would all follow, no matter the circumstances. One of them was that we’d always have dinner together in the evening, typically around 6pm.&lt;&#x2F;p&gt;
&lt;p&gt;In almost two decades, they never broke that rule. We had dinner on 9&#x2F;11 and when mom was at the hospital. It’s not always easy.&lt;&#x2F;p&gt;
&lt;p&gt;There’s a nice thing that happens when you have such a golden rule: it has ripple effects. Since we had dinner together every evening, we would always have time to talk about the day. Problems would be uncovered earlier. We would know about each other’s appointments for the next day. It provided structure throughout the rest of the day. It put things into perspective. It grounded us.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Bad grade at school? Dinner at 6.&lt;&#x2F;li&gt;
&lt;li&gt;Played computer games all afternoon and lost track of time? Dinner at 6.&lt;&#x2F;li&gt;
&lt;li&gt;No matter how bad your day was, dinner is always waiting for you.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;As a kid, it sounded like one of those “stupid” rules only grown-ups would come up with. And in fact, my parents knew that it was stupid. They did it anyway. As a kid, that made their life look extremely dull and boring. I remember pitying my dad once for being such a slave to society. Yet, they persisted because without it, things would fall apart. Skipping dinner is about way more than skipping dinner.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;these-rules-are-simple-but-not-easy&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#these-rules-are-simple-but-not-easy&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;These Rules Are Simple, But Not Easy&lt;&#x2F;h2&gt;
&lt;p&gt;It’s a simple rule with little room for interpretation. However, it’s not easy: there are times when you have to drop something else to make dinner at 6 work. That’s when the rule counts the most! That’s what makes or breaks it.&lt;&#x2F;p&gt;
&lt;p&gt;Following the rule 90% of the time is much easier than following it 100% of the time. You have to make sacrifices. You have to say no sometimes. That’s the price it takes to stick to the rule.&lt;&#x2F;p&gt;
&lt;p&gt;Yes, such rules “sound” stupid, but there’s a deeper, almost stoic realization to it:
Life is complicated and will throw obstacles in your way. But if you really want to make progress, you have to find a way. If nothing else helps, make up a stupid rule;
and the harder you struggle, the more specific the rule should be.&lt;&#x2F;p&gt;
&lt;p&gt;Dinner. Every day. At 6 o’clock.&lt;&#x2F;p&gt;
&lt;p&gt;Only now am I discovering this for myself. In 2019, I mentioned to my friend Abu that I felt bad for not doing any sports. It’s not that I didn’t try, it’s just that nothing lasted for long. He suggested going for a run together on Tuesdays – no matter what. I thought that was ridiculous. I told him that it couldn’t possibly work. Why Tuesdays of all days!? It felt so random. In my mind, I started negotiating. But there’s no point in negotiating with irrationality. Fast forward 5 years, and I still run every Tuesday.&lt;&#x2F;p&gt;
&lt;p&gt;I actually suck at running. My pace isn’t fast. The distance isn’t far, but it’s a solid effort. Time was made. It worked out. Again, it had positive rippling effects: I ran on Crete in Greece and Sardinia in Italy. Different people joined me on my runs. If Tuesday finds me elsewhere, my running shoes come along. Now, did I always manage to run on a Tuesday? No. It’s not easy! But I &lt;em&gt;always&lt;&#x2F;em&gt; gave it a solid attempt and I can remember each time I didn’t run. Since Abu and I run together a lot, we would talk about our week. If we didn’t make up that rule, we would never have started to know each other on such a deep level.&lt;&#x2F;p&gt;
&lt;p&gt;Some people won’t understand when you tell them that you have to do a thing “no matter what.” Instead of telling them I have to go for a run, I say I’m busy that evening. Nobody ever asks any questions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;isn-t-this-just-a-habit&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#isn-t-this-just-a-habit&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Isn’t this just a habit?&lt;&#x2F;h2&gt;
&lt;p&gt;With “no matter what” there can be serious consequences. If you have to take care of a loved one, you can’t skip a day. Or if you’re an Air Traffic Controller, failure is not an option.&lt;&#x2F;p&gt;
&lt;p&gt;My stakes are not as high, but I take them very seriously.&lt;&#x2F;p&gt;
&lt;p&gt;“No matter what” rules aren’t habits, at least not in the beginning. They can, however, turn into super strong habits with time.&lt;&#x2F;p&gt;
&lt;p&gt;I found that the best way to implement a “NMW Rule” is to do it on the spot. When my dentist asked me if I floss every day (I didn’t), I made the decision to start right then and there and never skip a day.&lt;&#x2F;p&gt;
&lt;p&gt;Another good way to get started is to take on some lightweight responsibility.
For example, I recommend getting plants.
Then you have to water them – no matter what.&lt;&#x2F;p&gt;
&lt;p&gt;If the plant dries out, you broke the rule; simple as that.
The great thing is that the watering interval is usually pretty low, so there’s time to get used to it
(but getting used to it you must).&lt;&#x2F;p&gt;
&lt;p&gt;If it works, you’ll enjoy the feeling of continuity.
It’s like a chain of good deeds.
A new habit is born.&lt;&#x2F;p&gt;
&lt;p&gt;In the past, I never had any plants.
Now our apartment is full of them.
I love the companionship and the continuity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-your-nmw&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-s-your-nmw&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;What’s your “NMW”?&lt;&#x2F;h2&gt;
&lt;p&gt;If you already have a “no matter what” rule, you have my deepest respect.&lt;&#x2F;p&gt;
&lt;p&gt;If not, whether you want to write that book, run that marathon, or just save a few bucks each month, make it work – no matter what.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Best Programmers I Know</title>
        <published>2025-04-04T00:00:00+00:00</published>
        <updated>2025-04-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2025/best-programmers/"/>
        <id>https://endler.dev/2025/best-programmers/</id>
        
        <content type="html" xml:base="https://endler.dev/2025/best-programmers/">&lt;p&gt;I have met a lot of developers in my life.
Lately, I asked myself: “What does it take to be one of the best? What do they all have in common?”&lt;&#x2F;p&gt;
&lt;p&gt;In the hope that this will be an inspiration to someone out there, I wrote down the traits I observed in the most exceptional people in our craft. I wish I had that list when I was starting out. Had I followed this path, it would have saved me a lot of time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;read-the-reference&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#read-the-reference&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Read the Reference&lt;&#x2F;h2&gt;
&lt;p&gt;If there was one thing that I should have done as a young programmer,
it would have been to &lt;em&gt;read the reference&lt;&#x2F;em&gt; of the thing I was using.
I.e. read the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;httpd.apache.org&#x2F;docs&#x2F;2.4&#x2F;&quot;&gt;Apache Webserver Documentation&lt;&#x2F;a&gt;,
the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.python.org&#x2F;3&#x2F;library&#x2F;index.html&quot;&gt;Python Standard Library&lt;&#x2F;a&gt;,
or the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;toml.io&#x2F;en&#x2F;v1.0.0&quot;&gt;TOML spec&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Don’t go to Stack Overflow, don’t ask the LLM, don’t &lt;em&gt;guess&lt;&#x2F;em&gt;, just go straight to the &lt;strong&gt;source&lt;&#x2F;strong&gt;.
Oftentimes, it’s surprisingly accessible and well-written.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;know-your-tools-really-well&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#know-your-tools-really-well&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Know Your Tools Really Well&lt;&#x2F;h2&gt;
&lt;p&gt;Great devs understand the technologies they use on a &lt;strong&gt;fundamental level&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It’s one thing to be able to &lt;em&gt;use&lt;&#x2F;em&gt; a tool and a whole other thing to truly &lt;em&gt;grok&lt;&#x2F;em&gt; (understand) it.
A mere user will fumble around, get confused easily, hold it wrong and not optimize the config.&lt;&#x2F;p&gt;
&lt;p&gt;An expert goes in (after reading the reference!)
and sits down to write a config for the tool of which they understand every single line and can explain it to a colleague.
That leaves no room for doubt!&lt;&#x2F;p&gt;
&lt;p&gt;To know a tool well, you have to know:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;its history: who created it? Why? To solve which problem?&lt;&#x2F;li&gt;
&lt;li&gt;its present: who maintains it? Where do they work? On what?&lt;&#x2F;li&gt;
&lt;li&gt;its limitations: when is the tool not a good fit? When does it break?&lt;&#x2F;li&gt;
&lt;li&gt;its ecosystem: what libraries exist? Who uses it? What plugins?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For example, if you are a backend engineer and you make heavy use of Kafka,
I expect you to know a lot about Kafka – not just things you read on Reddit.
At least that’s what I expect if you want to be one of the best engineers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;read-the-error-message&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#read-the-error-message&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Read The Error Message&lt;&#x2F;h2&gt;
&lt;p&gt;As in &lt;strong&gt;Really Read the Error Message and Try to Understand What’s Written&lt;&#x2F;strong&gt;.
Turns out, if you just sit and meditate about the error message, it starts to speak to you.
The best engineers can infer a ton of information from very little context.
Just by reading the error message, you can fix most of the problems on your own.&lt;&#x2F;p&gt;
&lt;p&gt;It also feels like a superpower if you help someone who doesn’t have that skill.
Like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.m.wikipedia.org&#x2F;wiki&#x2F;Tasseography&quot;&gt;“reading from a cup”&lt;&#x2F;a&gt; or so.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;break-down-problems&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#break-down-problems&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Break Down Problems&lt;&#x2F;h2&gt;
&lt;p&gt;Everyone gets stuck at times.
The best know how to get unstuck.
They simplify problems until they become digestible.
That’s a hard skill to learn and requires a ton of experience.
Alternatively, you just have awesome problem-solving skills, e.g., you’re clever.
If not, you can train it, but there is no way around breaking down hard problems.
There are problems in this world that are too hard to solve at once for anyone involved.&lt;&#x2F;p&gt;
&lt;p&gt;If you work as a professional developer, that is the bulk of the work you get paid to do:
breaking down problems.
If you do it right, it will feel like cheating:
you just solve simple problems until you’re done.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-be-afraid-to-get-your-hands-dirty&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#don-t-be-afraid-to-get-your-hands-dirty&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Don’t Be Afraid To Get Your Hands Dirty&lt;&#x2F;h2&gt;
&lt;p&gt;The best devs I know read a lot of code and they are not afraid to touch it.
They never say “that’s not for me” or “I can’t help you here.”
Instead, they just start and learn.
Code is &lt;em&gt;just code&lt;&#x2F;em&gt;.
They can just pick up any skill that is required with time and effort.
Before you know it, they become the go-to person in the team for whatever they touched.
Mostly because they were the only ones who were not afraid to touch it in the first place.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;always-help-others&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#always-help-others&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Always Help Others&lt;&#x2F;h2&gt;
&lt;p&gt;A related point.
Great engineers are in high demand and are always busy, but they always try to help.
That’s because they are naturally curious and their supportive mind is what made them great engineers in the first place.
It’s a sheer joy to have them on your team, because they are problem solvers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;write&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#write&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Write&lt;&#x2F;h2&gt;
&lt;p&gt;Most awesome engineers are well-spoken and happy to share knowledge.&lt;&#x2F;p&gt;
&lt;p&gt;The best have some outlet for their thoughts: blogs, talks, open source, or a combination of those.&lt;&#x2F;p&gt;
&lt;p&gt;I think there is a strong correlation between writing skills and programming.
All the best engineers I know have good command over at least one human language – often more.
Mastering the way you write is mastering the way you think and vice versa.
A person’s writing style says so much about the way they think.
If it’s confusing and lacks structure, their coding style will be too.
If it’s concise, educational, well-structured, and witty at times, their code will be too.&lt;&#x2F;p&gt;
&lt;p&gt;Excellent programmers find joy in playing with words.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;never-stop-learning&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#never-stop-learning&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Never Stop Learning&lt;&#x2F;h2&gt;
&lt;p&gt;Some of the best devs I know are 60+ years old.
They can run circles around me.
Part of the reason is that they keep learning.
If there is a new tool they haven’t tried or a language they like, they will learn it.
This way, they always stay on top of things without much effort.&lt;&#x2F;p&gt;
&lt;p&gt;That is not to be taken for granted: a lot of people stop learning really quickly after they
graduate from University or start in their first job.
They get stuck thinking that what they got taught in school is the “right” way to do things.
Everything new is bad and not worth their time.
So there are 25-year-olds who are “mentally retired” and 68-year-olds who are still fresh in their mind.
I try to one day belong to the latter group.&lt;&#x2F;p&gt;
&lt;p&gt;Somewhat related, the best engineers don’t follow trends, but they will always carefully
evaluate the benefits of new technology. If they dismiss it, they can tell you exactly &lt;em&gt;why&lt;&#x2F;em&gt;,
when the technology would be a good choice, and what the alternatives are.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;status-doesn-t-matter&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#status-doesn-t-matter&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Status Doesn’t Matter&lt;&#x2F;h2&gt;
&lt;p&gt;The best devs talk to principal engineers and junior devs alike. There is no hierarchy.
They try to learn from everyone, young and old.
The newcomers often aren’t entrenched in office politics yet and still have a fresh mind.
They don’t know why things are &lt;em&gt;hard&lt;&#x2F;em&gt; and so they propose creative solutions.
Maybe the obstacles from the past are no more, which makes these people a great source of inspiration.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;build-a-reputation&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#build-a-reputation&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Build a Reputation&lt;&#x2F;h2&gt;
&lt;p&gt;You can be a solid engineer if you &lt;strong&gt;do&lt;&#x2F;strong&gt; good work,
but you can only be one of the best if you’re &lt;strong&gt;known&lt;&#x2F;strong&gt; for your good work;
at least within a (larger) organization.&lt;&#x2F;p&gt;
&lt;p&gt;There are many ways to build a reputation for yourself:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You built and shipped a critical service for a (larger) org.&lt;&#x2F;li&gt;
&lt;li&gt;You wrote a famous tool&lt;&#x2F;li&gt;
&lt;li&gt;You contribute to a popular open source tool&lt;&#x2F;li&gt;
&lt;li&gt;You wrote a book that is often mentioned&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Why do I think it is important to be known for your work?
All of the above are ways to extend your radius of impact in the community.
Famous developers impact way more people than non-famous developers.
There’s only so much code you can write.
If you want to “scale” your impact, you have to become a thought leader.&lt;&#x2F;p&gt;
&lt;p&gt;Building a reputation is a long-term goal.
It doesn’t happen overnight, nor does it have to.
And it won’t happen by accident.
You show up every day and do the work.
Over time, the work will speak for itself.
More people will trust you and your work and they will want to work with you.
You will work on more prestigious projects and the circle will grow.&lt;&#x2F;p&gt;
&lt;p&gt;I once heard about this idea that your latest work should
overshadow everything you did before.
That’s a good sign that you are on the right track.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;have-patience&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#have-patience&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Have Patience&lt;&#x2F;h2&gt;
&lt;p&gt;You need patience with computers and humans.
Especially with yourself.
Not everything will work right away and people take time to learn.
It’s not that people around you are stupid; they just have incomplete information.
Without patience, it will feel like the world is against you and
everyone around you is just incompetent. That’s a miserable place to be.
You’re too clever for your own good.&lt;&#x2F;p&gt;
&lt;p&gt;To be one of the best, you need an incredible amount of patience, focus, and dedication.
You can’t afford to get distracted easily if you want to solve hard problems.
You have to return to the keyboard to get over it.
You have to put in the work to push a project over the finishing line.
And if you can do so while not being an arrogant prick, that’s even better.
That’s what separates the best from the rest.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;never-blame-the-computer&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#never-blame-the-computer&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Never Blame the Computer&lt;&#x2F;h2&gt;
&lt;p&gt;Most developers blame the software, other people, their dog, or the weather for
flaky, seemingly “random” bugs.&lt;&#x2F;p&gt;
&lt;p&gt;The best devs don’t.&lt;&#x2F;p&gt;
&lt;p&gt;No matter how erratic or mischievous the behavior of a computer seems,
there is &lt;em&gt;always&lt;&#x2F;em&gt; a logical explanation: you just haven’t found it yet!&lt;&#x2F;p&gt;
&lt;p&gt;The best keep digging until they find the reason.
They might not find the reason immediately, they might never find it,
but they never blame external circumstances.&lt;&#x2F;p&gt;
&lt;p&gt;With this attitude, they are able to make incredible progress and learn things that others fail to.
When you mistake bugs for incomprehensible magic, magic is what it will always be.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-be-afraid-to-say-i-don-t-know&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#don-t-be-afraid-to-say-i-don-t-know&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Don’t Be Afraid to Say “I Don’t Know”&lt;&#x2F;h2&gt;
&lt;p&gt;In job interviews, I pushed candidates hard to at least say “I don’t know” once.
The reason was not that I wanted to look superior (although some people certainly had that impression).
No, I wanted to reach the boundary of their knowledge.
I wanted to stand with them on the edge of what they thought they knew.
Often, I myself didn’t know the answer. And to be honest, I didn’t care about the answer.
What I cared about was when people bullshitted their way through the interview.&lt;&#x2F;p&gt;
&lt;p&gt;The best candidates said
“Huh, I don’t know, but that’s an interesting question! If I had to guess, I would say…”
and then they would proceed to deduce the answer.
That’s a sign that you have the potential to be a great engineer.&lt;&#x2F;p&gt;
&lt;p&gt;If you are afraid to say “I don’t know”, you come from a position of hubris or defensiveness.
I don’t like bullshitters on my team.
Better to acknowledge that you can’t know everything.
Once you accept that, you allow yourself to learn.
“The important thing is that you don’t stop asking questions,” said Albert Einstein.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-guess&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#don-t-guess&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Don’t Guess&lt;&#x2F;h2&gt;
&lt;p&gt;“In the Face of Ambiguity, Refuse the Temptation to Guess”
That is one of my favorite rules in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;peps.python.org&#x2F;pep-0020&#x2F;&quot;&gt;PEP 20 – The Zen of Python&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And it’s so, so tempting to guess!&lt;&#x2F;p&gt;
&lt;p&gt;I’ve been there many times and I failed with my own ambition.&lt;&#x2F;p&gt;
&lt;p&gt;When you guess, two things can happen:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;In the &lt;strong&gt;best case&lt;&#x2F;strong&gt; you’re wrong and your incorrect assumptions lead to a bug.&lt;&#x2F;li&gt;
&lt;li&gt;In the &lt;strong&gt;worst case&lt;&#x2F;strong&gt; you are right… and you’ll never stop and second guess yourself.
You build up your mental model based on the wrong assumptions.
This can haunt you for a long time.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Again, resist the urge to guess.
Ask questions, read the reference, use a debugger, be thorough.
Do what it takes to get the answer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keep-it-simple&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#keep-it-simple&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Keep It Simple&lt;&#x2F;h2&gt;
&lt;p&gt;Clever engineers write clever code.
Exceptional engineers write simple code.&lt;&#x2F;p&gt;
&lt;p&gt;That’s because most of the time, simple is enough.
And simple is more maintainable than complex.
Sometimes it &lt;em&gt;does&lt;&#x2F;em&gt; matter to get things right, but
knowing the difference is what separates the best from the rest.&lt;&#x2F;p&gt;
&lt;p&gt;You can achieve a whole lot by keeping it simple.
Focus on the right things.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#final-thoughts&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Final Thoughts&lt;&#x2F;h2&gt;
&lt;p&gt;The above is not a checklist or a competition;
and great engineering is not a race.&lt;&#x2F;p&gt;
&lt;p&gt;Just don’t trick yourself into thinking that you can skip the hard work.
There is no shortcut. Good luck with your journey.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>So You Want to Start a (Tech) Podcast</title>
        <published>2024-10-04T00:00:00+00:00</published>
        <updated>2024-10-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/so-you-want-to-start-a-tech-podcast/"/>
        <id>https://endler.dev/2024/so-you-want-to-start-a-tech-podcast/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/so-you-want-to-start-a-tech-podcast/">&lt;p&gt;For the past year, I’ve been hosting the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;podcast&#x2F;&quot;&gt;Rust in
Production&lt;&#x2F;a&gt;,
a podcast about companies who shape the future of infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;This journey has taught me a lot about what it takes to create and maintain a
successful podcast. Well, success is always relative; at the moment we have
around 5k regular (monthly) listeners. Maybe not a ton of people, but it puts us
comfortably into the top 5% of podcasts – at least by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.demandsage.com&#x2F;podcast-statistics&#x2F;&quot;&gt;some
statistics&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Whether you’re considering starting your own podcast or just curious about the
process, I hope my experiences can offer some valuable insights.&lt;&#x2F;p&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;corrode.dev&amp;#x2F;podcast&amp;#x2F;&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;so-you-want-to-start-a-tech-podcast&amp;#x2F;cover.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;so-you-want-to-start-a-tech-podcast&amp;#x2F;cover.jpg&quot; 
        
            alt=&quot;The &amp;#x27;Rust in Production&amp;#x27; podcast cover&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;650&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
        &lt;figcaption&gt;
            
            The ‘Rust in Production’ podcast cover
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;do-your-research&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#do-your-research&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Do Your Research&lt;&#x2F;h2&gt;
&lt;p&gt;Before you dive into the world of podcasting, take some time to explore the landscape. Think about branding and positioning &lt;strong&gt;first&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;topic&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#topic&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Topic&lt;&#x2F;h3&gt;
&lt;p&gt;When choosing your topic, make sure it’s something you can easily generate ideas
for. Try to come up with at least 10 potential episode ideas
before you settle on it. If you’re
planning an interview-based podcast, ensure you have a large enough network to
secure at least 10 guests.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;competition&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#competition&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Competition&lt;&#x2F;h3&gt;
&lt;p&gt;Research your competition. Listen to similar podcasts and note down what you like and dislike about them. This will help you differentiate your podcast from others in the same niche.&lt;&#x2F;p&gt;
&lt;p&gt;If a podcast is already covering your topic, that’s not necessarily a bad thing; it just shows there’s an audience for it. However, you need to find a unique angle or a different format to stand out. If you can’t be the first, be the best. Be the funniest, or the most in-depth, or the one with the most interesting guests.&lt;&#x2F;p&gt;
&lt;p&gt;Be honest with yourself about what you can offer that others can’t. If you can’t find a unique angle, it might be better to choose a different topic.
If you’re not sure, ask your friends or colleagues for their opinion.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;podcast-name&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#podcast-name&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Podcast Name&lt;&#x2F;h3&gt;
&lt;p&gt;What’s the title of your podcast?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Is it catchy and easy to remember?&lt;&#x2F;li&gt;
&lt;li&gt;Does it convey what your podcast is about?&lt;&#x2F;li&gt;
&lt;li&gt;Is the domain name available?&lt;&#x2F;li&gt;
&lt;li&gt;Are the social media handles available?&lt;&#x2F;li&gt;
&lt;li&gt;Is there a simple abbreviation you can use for hashtags or mentions?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Especially the last few points are often overlooked. You want to make it as easy as possible for people to find your podcast.
I’d say don’t be too clever with your podcast name. It should be easy to remember and spell. If you have to explain it, it’s probably too complicated. Also, don’t use special characters or numbers in your podcast name. It makes it harder to remember and type.
Don’t pick a too generic name either. Be specific about your niche. So instead of “The JavaScript Podcast,” go for “Refactoring JavaScript” or
“React Weekly.”&lt;&#x2F;p&gt;
&lt;p&gt;Don’t forget about SEO. Consider what people might search for when looking for content like yours. My podcast is titled “Rust in Production,” which is a commonly searched term. This has helped with discoverability.
Another version of that, which could work, is to think about questions that people Google for.
E.g. “What is functional programming?” or “How to refactor legacy code?”
and then coming up with a podcast name that answers that question.
For example, “Functional Programming Explained” or “Refactoring Legacy Code.”&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cover-art&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#cover-art&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Cover Art&lt;&#x2F;h3&gt;
&lt;p&gt;Your podcast’s cover is equally crucial. It’s the first thing people recognize about your podcast (except for the title) before they decide what to listen to, so it needs to stand out from the crowd.&lt;&#x2F;p&gt;
&lt;p&gt;What I did was open my podcast app and look at the grid of covers.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;so-you-want-to-start-a-tech-podcast&amp;#x2F;podcasts.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;so-you-want-to-start-a-tech-podcast&amp;#x2F;podcasts.jpg&quot; 
        
            alt=&quot;The grid of podcast covers in my podcast app&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;1295&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            The grid of podcast covers in my podcast app
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;I asked myself which ones stood out and why.
I also asked a few friends and my partner to do the same. I got some great feedback that way.
This visual first impression can make a big difference in attracting new listeners.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;length&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#length&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Length&lt;&#x2F;h3&gt;
&lt;p&gt;Next, decide on your podcast’s length. Fifteen minutes is great for news content, 30 minutes work well for commutes, and one hour is suitable for deep dives. Anything longer, and listeners might hesitate to commit their time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;plan-your-content&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#plan-your-content&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Plan Your Content&lt;&#x2F;h2&gt;
&lt;p&gt;Once you’ve done your research, it’s time to plan your content strategy. Having a regular schedule is key - weekly or biweekly episodes work well for many podcasts. Start conservatively; you can always increase frequency later, but underestimating the workload can lead to burnout.&lt;&#x2F;p&gt;
&lt;p&gt;I highly recommend buffering content by recording a few episodes before you start publishing. This gives you a cushion and reduces stress, especially when you’re just starting out.&lt;&#x2F;p&gt;
&lt;p&gt;Consider a season-based approach. For “Rust in Production,” we do 7-8 episodes and then take a break. This allows for better planning and reduces ongoing pressure.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;respect-your-guests&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#respect-your-guests&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Respect Your Guests&lt;&#x2F;h2&gt;
&lt;p&gt;If you’re doing an interview-based podcast, treating your guests with respect is paramount. Explain why you want them on your show in the initial email. Keep them informed about the process and be flexible with scheduling. At the start of the recording, explain how things will work and ask if they have any time constraints.&lt;&#x2F;p&gt;
&lt;p&gt;Remember, your guests are likely doing this for free. Respect their time and make the experience as smooth as possible for them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;invest-in-quality&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#invest-in-quality&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Invest in Quality&lt;&#x2F;h2&gt;
&lt;p&gt;Audio quality can make or break a podcast. Invest in good equipment - get a decent microphone and headphones, and consider ways to improve your room’s acoustics. If you’re interviewing guests remotely, consider their equipment too. A pre-call to check their setup can be invaluable, or you might even consider sending them equipment if you want consistent quality across episodes.&lt;&#x2F;p&gt;
&lt;p&gt;Always remind guests to stay close to the mic. It’s a small detail that can make a big difference in audio quality.
On two occasions, I had guests who had their condenser mic backwards, and that sounds pretty dull. You get better at picking up on these things the more you record. It helps to know which way the mic should be facing (usually the logo on the mic and the volume knob should be facing you). Both guests were very grateful for the tip and the audio quality improved significantly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;production-tips&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#production-tips&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Production Tips&lt;&#x2F;h2&gt;
&lt;p&gt;One of the best decisions I made was not to edit the podcast myself. I’m incredibly thankful that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;M3t0r&quot;&gt;Simon Brüggen&lt;&#x2F;a&gt; agreed to do the editing for “Rust in Production.” It would have been an enormous amount of work on top of finding guests, recording, and hosting.
It also helps that Simon is a Rust developer and understands the content. He can give tips on how to improve the content from a technical perspective.&lt;&#x2F;p&gt;
&lt;p&gt;For recording, tools like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zencastr.com&#x2F;&quot;&gt;Zencastr&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;riverside.fm&#x2F;&quot;&gt;Riverside&lt;&#x2F;a&gt;, or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.descript.com&#x2F;&quot;&gt;Descript&lt;&#x2F;a&gt; are excellent. They capture audio on both sides, giving you uncompressed files to work with. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;auphonic.com&#x2F;&quot;&gt;Auphonic&lt;&#x2F;a&gt; is great for cleaning up audio, removing filler words, and creating transcripts.&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to hosting, I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;letscast.fm&#x2F;&quot;&gt;Letscast&lt;&#x2F;a&gt;. They’re not the cheapest option, but their customer service is top notch and the website is fast and not bloated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;develop-your-style&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#develop-your-style&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Develop Your Style&lt;&#x2F;h2&gt;
&lt;p&gt;As you progress, you’ll naturally develop your own podcasting style. For me, I prefer to let guests do most of the talking, only interjecting occasionally with questions or comments.
The motto is “say less, ask more.” It’s a good rule of thumb for interviews. It’s not about you, it’s about the guest. Let them shine.
In pursuit of asking better questions, I wrote an essay on &lt;a href=&quot;&#x2F;2024&#x2F;asking-better-questions&#x2F;&quot;&gt;how to ask better questions&lt;&#x2F;a&gt;.
I’ve also found that taking notes during recording helps me ask better follow-up questions.&lt;&#x2F;p&gt;
&lt;p&gt;Don’t be afraid to encourage your guests when they make good points. A nod, a smile, or a thumbs up can go a long way in making them feel comfortable and valued.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-sweat-the-small-stuff&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#don-t-sweat-the-small-stuff&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Don’t Sweat the Small Stuff&lt;&#x2F;h2&gt;
&lt;p&gt;While it’s tempting to obsess over metrics, try not to focus on them too much. Instead, concentrate on producing content you’d enjoy consuming yourself. Be passionate about your topic and create your podcast as if no one is listening - ironically, this often leads to the most engaging content.&lt;&#x2F;p&gt;
&lt;p&gt;Starting a podcast is a lot of work, but it’s incredibly rewarding. The podcast space isn’t oversaturated yet - it
reminds me of the golden age of YouTube a few years ago. Podcasting is becoming more professional now, but there’s still plenty of room for new formats and perspectives.&lt;&#x2F;p&gt;
&lt;p&gt;Remember: it’s okay to start small and grow. You’ll learn and improve with each new episode. The most important thing is to enjoy the process and share your personality with the world.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re interested in Rust, consider listening to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;podcast&#x2F;&quot;&gt;Rust in Production&lt;&#x2F;a&gt; podcast. I’d love to hear what you think!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Follow the Hackers</title>
        <published>2024-09-07T00:00:00+00:00</published>
        <updated>2024-12-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/follow-the-hackers/"/>
        <id>https://endler.dev/2024/follow-the-hackers/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/follow-the-hackers/">&lt;p&gt;Want to see tomorrow’s important technologies?
Watch what hackers are passionate about today.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;defining-hacker&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#defining-hacker&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Defining “Hacker”&lt;&#x2F;h2&gt;
&lt;p&gt;I’m using the term “hacker” in the spirit of the Hacker Ethic, as described by authors like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Steven_Levy&quot;&gt;Steven Levy&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pekka_Himanen&quot;&gt;Pekka Himanen&lt;&#x2F;a&gt;.
In this context, a hacker is someone who:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Follows their passion and seeks self-fulfillment through technology&lt;&#x2F;li&gt;
&lt;li&gt;Creates something beneficial for the wider community&lt;&#x2F;li&gt;
&lt;li&gt;Values freedom, cooperation, and voluntary work&lt;&#x2F;li&gt;
&lt;li&gt;Challenges traditional work ethics with a focus on creativity and sharing&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These folks are a small subset of the population, but they have some traits that make them excellent predictors of the future:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;They care deeply about their field - programming being just one example&lt;&#x2F;li&gt;
&lt;li&gt;They’re passionate about the things they believe in&lt;&#x2F;li&gt;
&lt;li&gt;They’d use something even if no one else cared about it&lt;&#x2F;li&gt;
&lt;li&gt;They work at the cutting edge, so they need the best tools to do their job&lt;&#x2F;li&gt;
&lt;li&gt;They hold strong opinions on what works and what doesn’t, backed by solid evidence&lt;&#x2F;li&gt;
&lt;li&gt;They don’t care about investors, quarterly earnings reports, or politics - they purely focus on the technology’s value&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;catalysts-for-success-and-red-flags&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#catalysts-for-success-and-red-flags&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Catalysts For Success And Red Flags&lt;&#x2F;h2&gt;
&lt;p&gt;Of course, not every hyped technology makes it big.
Remember NFTs or Web3?&lt;&#x2F;p&gt;
&lt;p&gt;The key difference?
Real hackers were never passionate about these technologies - ordinary people were.
Another red flag is when the technology’s benefits are hard to explain.
If hardcore tech people can’t explain the benefits to you, that’s a bad sign.
Look deeper and you’ll find different motivations at work!&lt;&#x2F;p&gt;
&lt;p&gt;It’s typically people looking to profit from technology.
They brand themselves as Investors, “Serial Entrepreneurs”, and “Thought Leaders”.
You’ll find them on LinkedIn, updating their profiles with the latest buzzwords every few months.
While a few are legitimate, most are opportunists who couldn’t explain the technology to save their lives.
Profit is their only motivation.&lt;&#x2F;p&gt;
&lt;p&gt;The hackers?
They don’t care what you think about them.
They’ve got nothing to sell you.
They’re too busy building cool stuff!&lt;&#x2F;p&gt;
&lt;p&gt;A question hackers care about is “who owns the platform”?
Companies always have an agenda.
Pour in your time and effort, and they might lock you out to profit from your work.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=39772562&quot;&gt;Hackers don’t like that.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Therefore, all the winning ideas I mentioned are open source.
If a technology isn’t, that’s a major red flag when evaluating its future potential.
It’s not even optional anymore - it’s pretty much mandatory.&lt;&#x2F;p&gt;
&lt;p&gt;But there’s another reason why open source is a catalyst for success:
Initially, open source projects start as minimally functional versions without user-friendly documentation.
They might be tough to set up, but the core idea is there.
If people stick with it despite the lack of hand-holding, you know it’s solving a real problem - and that’s a sign of a winning idea.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;you-still-need-patience&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#you-still-need-patience&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;You Still Need Patience&lt;&#x2F;h2&gt;
&lt;p&gt;You probably know I’m all in on Rust.
After all, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&quot;&gt;I make my living as a Rust consultant&lt;&#x2F;a&gt;.
It took Rust over a decade of development to gain any real traction in the industry.
It’s been a slow but steady climb.&lt;&#x2F;p&gt;
&lt;p&gt;It takes time for the public to catch up before a technology hits its stride.
For core technologies like programming languages or databases, it often takes a decade or more.
That’s simply how long technology needs to mature.&lt;&#x2F;p&gt;
&lt;p&gt;That’s why I tell founders to stay slightly conservative when adopting new tech.
The industry needs time to catch up, and big companies need specialized tools to integrate new tech into their existing systems.
On the other side, investing early in promising technologies is a calculated risk because the writing is on the wall.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-can-you-learn-from-this&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-can-you-learn-from-this&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;What Can You Learn From This?&lt;&#x2F;h2&gt;
&lt;p&gt;Hackers are already living in the future.
You can use that to your advantage.
Ask 10 hackers what new things they’re really excited about, and you’ll get a good picture of what’s going to be important in a few years.&lt;&#x2F;p&gt;
&lt;p&gt;Most business people don’t talk to hackers regularly.
That’s a fact you can use to your advantage.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re selling to developers (&lt;a href=&quot;&#x2F;2024&#x2F;selling-to-developers&#x2F;&quot;&gt;and you probably shouldn’t&lt;&#x2F;a&gt;), the key is to really listen to what the hackers are saying and then follow their lead.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Be Simple</title>
        <published>2024-09-02T00:00:00+00:00</published>
        <updated>2024-09-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/be-simple/"/>
        <id>https://endler.dev/2024/be-simple/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/be-simple/">&lt;p&gt;Last night I realized that my life is very simple.
That’s not by chance, but by conscious effort.
Life becomes complex all by itself if you do nothing about it.&lt;&#x2F;p&gt;
&lt;p&gt;One day you’ll wake up and you have a mortgage, 10 on-demand subscriptions, 20 insurances, 1000 open browser tabs, a demanding job and a dog.
And when you realize it, you wonder how you got there.&lt;&#x2F;p&gt;
&lt;p&gt;I keep my life simple because I know my time is limited.
Time and health are my best proxies for happiness.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simple-doesn-t-mean-boring&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#simple-doesn-t-mean-boring&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Simple Doesn’t Mean Boring&lt;&#x2F;h2&gt;
&lt;p&gt;Quite the contrary: give me enough time and I find ways to entertain myself.
My friends might disagree, but I consider myself to be an introvert.
I like to spend time on my own to explore and learn.
There hasn’t been a boring moment in a long time.&lt;&#x2F;p&gt;
&lt;p&gt;If life was more complex, that would take away my time, but time is the resource I can’t replenish, so I protect it.
How? Mostly by saying NO.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;No streaming subscriptions. No Disney+, no Netflix. I rarely watch TV anyway.&lt;&#x2F;li&gt;
&lt;li&gt;No gym memberships. Just run in the park.&lt;&#x2F;li&gt;
&lt;li&gt;No Instagram or TikTok, but part of that is getting older.&lt;&#x2F;li&gt;
&lt;li&gt;My shoes are 6 years old. So is my wardrobe.&lt;&#x2F;li&gt;
&lt;li&gt;No meetings if possible. I’m the guy who sits at his desk for 8 hours straight, only getting up for bathroom breaks twice.&lt;&#x2F;li&gt;
&lt;li&gt;No property; I’m a happy tenant.&lt;&#x2F;li&gt;
&lt;li&gt;No commute; I work remotely.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Great home cinema setup you have there.
Thanks for inviting me over!
At home, I don’t even have external speakers.&lt;&#x2F;p&gt;
&lt;p&gt;You’re planning a trip to the Bahamas? Enjoy! Send me a photo.&lt;&#x2F;p&gt;
&lt;p&gt;Regarding technology, that means:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Even though I’m a programmer, I only have a single screen.&lt;&#x2F;li&gt;
&lt;li&gt;I evaluate tools, but I keep the number of tools limited.&lt;&#x2F;li&gt;
&lt;li&gt;My editor doesn’t have a debugger.&lt;&#x2F;li&gt;
&lt;li&gt;No Notion or Obsidian if a text file + git is enough.&lt;&#x2F;li&gt;
&lt;li&gt;I limit the number of browser tabs with an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kanru&#x2F;max-tabs&quot;&gt;extension&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;simple-doesn-t-mean-minimalistic&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#simple-doesn-t-mean-minimalistic&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Simple Doesn’t Mean Minimalistic&lt;&#x2F;h2&gt;
&lt;p&gt;My goal is not to have as few possessions as possible – I own a lot – but to lead a simple life.
I’ll happily buy things if they make my life simpler.
The last big life improvements were a robot vacuum cleaner (four years ago) and an automated cat litter box (two years ago).
If I decide to buy something, I make sure it’s the absolute best I can afford.
(My rule is actually “don’t buy crap”.)
For example, I spent a ridiculous amount on the best laptop I could buy.
It’s my daily driver that I spend most of my time with, so it needs to be an absolute workhorse.
My work is also compute-intensive, so I saw the purchase as justified.&lt;&#x2F;p&gt;
&lt;p&gt;I always pay the price in full. No lease, no monthly payments.
I have to use services for work, but I prefer monthly payments over yearly subscriptions, even if they are 30% more expensive.
The fact that I can cancel at any time is more important to me.&lt;&#x2F;p&gt;
&lt;p&gt;I know that when I buy something, it demands my attention.
Maintenance is not fun.
Even though I like the &lt;em&gt;idea&lt;&#x2F;em&gt; of owning something, I probably don’t truly own it.
That makes me the worst consumer possible.
I keep things in my Amazon basket &lt;em&gt;forever&lt;&#x2F;em&gt;. From time to time I look at the items, and when I enjoy seeing them in my basket… I keep them there.
The rest, I just delete.
This way, I get the “feeling” of owning things without spending any money.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simple-doesn-t-mean-convenient&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#simple-doesn-t-mean-convenient&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Simple Doesn’t Mean Convenient&lt;&#x2F;h2&gt;
&lt;p&gt;To live with such a person is not easy.
We have regular discussions about “investing” money into things that I’m skeptical about.
It takes me ages to reach a conclusion.
Vacation planning is definitely one of my weaknesses.
I am very well aware that my approach is not perfect at times.
I am okay with making these sacrifices for protecting my time and therefore my happiness.&lt;&#x2F;p&gt;
&lt;p&gt;Recently, I got a few emails from people telling me that my newsletter subscription is broken.
I’m aware of that. My newsletter provider shut down.
I won’t fix it.
It turns out that people find other ways to follow me; either on Mastodon or via RSS.
I also don’t have a comment section – Reddit or HN work just fine.
Even though there are a few folks on my old newsletter list, I never got around to sending many emails.
I don’t particularly enjoy writing a newsletter, so it might be best that it finally broke.
I will probably remove the signup box.
It would be nice to have it “just work”, but the next best thing is to not have it at all.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simple-means-letting-go&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#simple-means-letting-go&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Simple Means Letting Go&lt;&#x2F;h2&gt;
&lt;p&gt;Perhaps another way to explain it is the midwit theme:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;be-simple&amp;#x2F;midwit.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;be-simple&amp;#x2F;midwit.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;367&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;I try to stay on the left side of this curve as much as I can.&lt;&#x2F;p&gt;
&lt;p&gt;I’m aware that there are “smarter” ways to do things, but I don’t want to dedicate time to learning about them.
I only dedicate time to things that matter to me and that I want to go really deep into.&lt;&#x2F;p&gt;
&lt;p&gt;The meme shows simple approaches on both ends, with a complicated phase in between.
Getting to the right side of the spectrum takes lots of effort, and I’ve only made that journey a few times in my life.
For the rest, knowing there’s an awkward complicated phase in between keeps me happily on the simple side.
It’s fine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simple-means-focused&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#simple-means-focused&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Simple Means Focused&lt;&#x2F;h2&gt;
&lt;p&gt;Greatness comes from dedicating time to the things that matter.
The most productive people I know are focused.
Yes, there’s a creative process and they allow themselves to be creative, but they do so in a very constrained environment: their office.
While others chase trends, they do the thing they’re always doing.
They put in the hours.&lt;&#x2F;p&gt;
&lt;p&gt;It’s way easier to be focused when life is simple.
When there’s no room for distractions and complexity.
I find that constraints help as well.
Technology is one major source of distraction.
Some of the best stories were written with a typewriter.
In itself, it’s a very limited environment, but it takes away all the distractions and lets you focus on the task at hand.
I find that inspiring, liberating.
That’s why I like constraints.
When I give presentations, I wonder what I’d write if I could only have 5 slides with 5 words each,
or I could only use two colors, or only show images.
It keeps me focused on the message.
It’s simple.
Simple is beautiful.
Simple makes me happy.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What to Write</title>
        <published>2024-08-20T00:00:00+00:00</published>
        <updated>2024-08-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/what-to-write/"/>
        <id>https://endler.dev/2024/what-to-write/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/what-to-write/">&lt;p&gt;People sometimes ask me how I come up with things to write.
To me, it’s the same as asking how I come up with things to say.
There’s always something to say.
It might not be novel or interesting to most, but it’s important to me
and hopefully to someone else.&lt;&#x2F;p&gt;
&lt;p&gt;What people &lt;em&gt;actually&lt;&#x2F;em&gt; want to know is how to come up with something &lt;em&gt;interesting&lt;&#x2F;em&gt; to write.
But why should that matter?
What if people don’t find it interesting?
Was it a waste of time?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-write&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-write&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Why Write?&lt;&#x2F;h2&gt;
&lt;p&gt;There’s this funny thing which happens when you write for a while:
you forget what excited you about writing in the first place.
Instead, you find yourself chasing trends, trying to get more views, and build a following.
Even if you’re aware that this is happening, it’s hard to stop.
Your inner monologue tells you that what you’re writing isn’t good enough
or that your readers won’t like it.&lt;&#x2F;p&gt;
&lt;p&gt;Writing becomes a chore.&lt;br &#x2F;&gt;
Eventually, you stop writing.&lt;&#x2F;p&gt;
&lt;p&gt;Somewhat tautologically, people come here exactly for one reason: to read what I write.
If I make it about them, I have to guess what they want to hear, which kills the joy in writing,
and also, in reading, as the content becomes predictable.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;interesting-doesn-t-mean-novel&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#interesting-doesn-t-mean-novel&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;&lt;em&gt;Interesting&lt;&#x2F;em&gt; Doesn’t Mean &lt;em&gt;Novel&lt;&#x2F;em&gt;.&lt;&#x2F;h2&gt;
&lt;p&gt;Just because someone else wrote about the same topic doesn’t mean it’s off-limits.
There are a million love songs to disprove that.
As it turns out, while they all revolve around the same topic, they’re all unique.
They are &lt;em&gt;personal&lt;&#x2F;em&gt;, which is what makes them different.&lt;&#x2F;p&gt;
&lt;p&gt;Some of these songs I like because I can relate to them.
To me, that’s what makes them interesting: it’s the same story but told in a different way – a personal way.
And that &lt;em&gt;personal&lt;&#x2F;em&gt; makes it &lt;em&gt;new&lt;&#x2F;em&gt; and that &lt;em&gt;new&lt;&#x2F;em&gt; makes it &lt;em&gt;interesting&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;if-you-take-away-the-personal-you-take-away-the-interesting&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#if-you-take-away-the-personal-you-take-away-the-interesting&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;If You Take Away the Personal, You Take Away the Interesting&lt;&#x2F;h2&gt;
&lt;p&gt;Writing is a lot like that.
I get to learn about how other people &lt;em&gt;feel&lt;&#x2F;em&gt; and how they think.
It’s mostly an experience; shaped into words.&lt;&#x2F;p&gt;
&lt;p&gt;It’s beautiful to think how writing is such a simple way to learn from the experiences of others.
And how, with just a few words, you can emotionally connect with a stranger.
It’s a very human experience.&lt;&#x2F;p&gt;
&lt;p&gt;Often, what you leave out is more important than what you keep; the reader fills in the blanks.
Eventually, a story starts a life of its own; when it gets shared; when it gets retold.
It’s no longer the author’s story but the reader’s.
It becomes part of lore.
Who wrote it isn’t that important.&lt;&#x2F;p&gt;
&lt;p&gt;I can’t tell who reads this and why should I care?
Instead of trying to make other people enjoy my writing, I want to connect with people who like the same topics.
Big difference.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;knowing-that-is-liberating&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#knowing-that-is-liberating&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Knowing That Is Liberating&lt;&#x2F;h2&gt;
&lt;p&gt;It gives me confidence that I will never run out of things to write.
At least not as long as I remember why I write.&lt;&#x2F;p&gt;
&lt;p&gt;It’s liberating because I don’t have to chase the &lt;em&gt;new&lt;&#x2F;em&gt;.
Instead, whatever it turns out to be is enough.
At times, I’m as clueless as the reader to see where this leads me.
Maybe someone else will find joy in it, maybe not.&lt;&#x2F;p&gt;
&lt;p&gt;It doesn’t matter.&lt;&#x2F;p&gt;
&lt;p&gt;What matters is what &lt;em&gt;you&lt;&#x2F;em&gt; think matters, and &lt;em&gt;that’s&lt;&#x2F;em&gt; what you should write about.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Move Slow and Fix Things</title>
        <published>2024-08-15T00:00:00+00:00</published>
        <updated>2024-08-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/move-slow-and-fix-things/"/>
        <id>https://endler.dev/2024/move-slow-and-fix-things/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/move-slow-and-fix-things/">&lt;p&gt;Growing up as a kid in rural Bavaria, I always dreamed of moving to the US to run a startup.
Many kids in my generation shared that dream.
To me, it felt like the &lt;em&gt;only&lt;&#x2F;em&gt; way to combine my two greatest passions: writing code and building things.&lt;&#x2F;p&gt;
&lt;p&gt;As I got older, I became disillusioned with the narrative surrounding Silicon Valley.
The hockey stick growth, the VC money, the “get rich quick” mentality – it was all one big illusion.
For a long time, I couldn’t put my finger on what exactly bothered me about it.&lt;&#x2F;p&gt;
&lt;p&gt;Part of what made me increasingly uncomfortable was the glorification of hustle culture –
the idea that you have to work yourself to the bone to make it big against all odds.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;move-slow-and-fix-things&amp;#x2F;work.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;move-slow-and-fix-things&amp;#x2F;work.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;328&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;The other part was the “winner takes all” mentality and the mindset that you have to “move fast and break things” to succeed.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t believe that has to be the case.&lt;&#x2F;p&gt;
&lt;p&gt;As it turns out, I’ve always been drawn to the &lt;em&gt;exact opposite&lt;&#x2F;em&gt;:
sustainable growth, robust solutions, and a long-term mindset.
That’s why I’ve been contributing to &lt;a href=&quot;&#x2F;2021&#x2F;oss-money&quot;&gt;open source for 15 years&lt;&#x2F;a&gt;, why I only run &lt;a href=&quot;&#x2F;2021&#x2F;codeprints&#x2F;&quot;&gt;small, bootstrapped businesses&lt;&#x2F;a&gt; or &lt;a href=&quot;&#x2F;2020&#x2F;sponsors&#x2F;&quot;&gt;non-profits&lt;&#x2F;a&gt;,
and why I focus on writing and knowledge sharing.&lt;&#x2F;p&gt;
&lt;p&gt;Paul Graham and his VC buddies would have you believe that your ultimate goal as a founder should be to build a unicorn.
But when I look at the Ubers, Facebooks, and Googles of this world, I see greed, gatekeeping, systemic exploitation, user tracking,
excessive resource consumption, and lawsuits against competitors.
These companies will do anything in their power to stay on top – even if it means bending the law or finding legal loopholes.
What kind of role model is that?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-other-side&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-other-side&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Other Side&lt;&#x2F;h2&gt;
&lt;p&gt;Who’s on the “other side”?
It’s the humble minority building small but meaningful things.
These people advocate for privacy, develop civic tech, try to live within their means, move deliberately, and fix what’s broken.
They fly under the radar because their success isn’t measured in dollars, and they lack big marketing budgets.
Instead, they focus on their product, doing a lot with very little.
I find that far more inspiring.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;move-slow-and-fix-things&amp;#x2F;bootstrap.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;move-slow-and-fix-things&amp;#x2F;bootstrap.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;352&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;It’s incredibly rewarding to build something people love that can provide you with a comfortable living.
There’s no need to risk it all, drop out of college, work insane hours, and leave a trail of destruction in your wake.
You can build something small and useful instead, without a venture capitalist breathing down your neck.
It’s still hard work, but you’re leaving the campsite a little better than you found it.&lt;&#x2F;p&gt;
&lt;p&gt;Note that moving slowly doesn’t mean you can’t make quick decisions.
It’s just that the execution should be deliberate.
Don’t wreak havoc along the way.
Because the time to fix what you might break rarely comes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vcs-are-not-your-friends&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#vcs-are-not-your-friends&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;VCs are Not Your Friends&lt;&#x2F;h2&gt;
&lt;p&gt;In &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;paulgraham.com&#x2F;notnot.html&quot;&gt;“Why to Not Not Start a Startup”&lt;&#x2F;a&gt;, Paul Graham writes:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;So, paradoxically, if you’re too inexperienced to start a startup, what you should do is start one. That’s a way more efficient cure for inexperience than a normal job. In fact, getting a normal job may actually make you less able to start a startup, by turning you into a tame animal who thinks he needs an office to work in and a product manager to tell him what software to write.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Let me be blunt: that’s nonsense. It paints a black and white picture of the world that simply doesn’t exist.
You don’t have to choose between starting a startup and working a soul-crushing job as a “tame animal” in a cubicle.
There’s a whole spectrum of possibilities in between!
For instance, you could work for yourself or with a small team, making use of your creativity and coming up with your own ideas.&lt;&#x2F;p&gt;
&lt;p&gt;Paul &lt;em&gt;wants&lt;&#x2F;em&gt; you to start a startup because he wants to fund you and profit from your hard work. His motives are purely egoistical.&lt;&#x2F;p&gt;
&lt;p&gt;If you happen to hit the startup jackpot, Paul gets even richer and you might become wealthy too. If you don’t, you’re left with nothing while Paul, already rich, gets to write an essay about your failure.&lt;&#x2F;p&gt;
&lt;p&gt;That’s a whole lot of risk for very little upside.&lt;&#x2F;p&gt;
&lt;p&gt;You might wonder why I’m picking on Paul Graham so much.
It’s because I once looked up to him and valued his essays.
He represents a worldview I used to believe in, but now consider harmful.
Most of his essays seem true on the surface, but dig deeper and you’ll find his claims are based on a narrow worldview and rarely supported by evidence.&lt;&#x2F;p&gt;
&lt;p&gt;Misleading young, impressionable people is dangerous.&lt;&#x2F;p&gt;
&lt;p&gt;Startup founders bear all the downside risk, while venture capitalists are well-insulated from failure. VCs spread their bets across numerous startups, ensuring they profit regardless of individual outcomes. For you, the founder, it’s an all-or-nothing gamble with your time, energy, and often your financial stability.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;is-all-vc-money-bad&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#is-all-vc-money-bad&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Is All VC Money Bad?&lt;&#x2F;h2&gt;
&lt;p&gt;Of course not. But I’d argue it’s becoming less and less relevant in today’s world.
Take building a software product, for example. You don’t need a fortune to get started anymore. There are website builders, cloud hosting solutions, and open source software at your fingertips.
Why take on VC money when you’re just starting out?
Some might argue that you profit from valuable networking opportunities and business advice along with the funding.
But most of that information is freely available online these days. There’s an abundance of podcasts, videos, and books on the subject if you’re willing to learn.&lt;&#x2F;p&gt;
&lt;p&gt;It’s trickier, of course, if you’re building a physical product.
But even that has become much easier in recent years.
Could you sell a 3D printed prototype before scaling up production?
Or launch a Kickstarter campaign to fund your first batch of products?
There are now print-on-demand services for t-shirts, mugs, posters, and books.
Plus, there are plenty of brick-and-mortar stores you could approach with your business idea if you’re looking to collaborate.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s say you do become wildly successful and urgently need capital to scale. Maybe then VC money is one way to go. Or you could take out a loan.
Either way, remember that money always comes with strings attached.
Funding might force you to do things you’re not comfortable with, like compromising your users’ privacy or your own values.
And even if not, you’ll constantly be pressured to find new avenues for growth.
Wouldn’t it be nicer to focus on making your product better instead?
That’s often far more rewarding.
But often, if you spend enough time thinking through a problem, you might find a way to prove your concept at a smaller scale.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;there-is-no-infinite-growth&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#there-is-no-infinite-growth&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;There Is No Infinite Growth&lt;&#x2F;h2&gt;
&lt;p&gt;Ask yourself: What truly motivates you? Is it power, money, or fame?
If so, there are more meaningful things in life.
Your self-worth isn’t tied to building a unicorn.
I don’t know who needs to hear this, but it’s perfectly fine to be 23 and not be a millionaire founder.
If you’re a high school or college student dreaming of running a startup, know that there’s another path.&lt;&#x2F;p&gt;
&lt;p&gt;Don’t sell out your moral compass for a quick buck.
You don’t have to jump on the AI bandwagon just because it’s the flavor of the month.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ycombinator.com&#x2F;companies?batch=W24&amp;amp;tags=Artificial%20Intelligence&amp;amp;tags=AI&amp;amp;tags=Generative%20AI&amp;amp;tags=AI%20Assistant&quot;&gt;At least 144 out of 251 companies&lt;&#x2F;a&gt; from the YC W24 batch are building products with “AI”.
That’s 57% of the batch.
How many of them are actually doing something meaningful with it?
How many will still be around in 5 years? What lasting value do these companies bring to the world?
We’re accumulating a massive amount of tech debt while rewarding short-term thinking and profit over sustainability.&lt;&#x2F;p&gt;
&lt;p&gt;Sure, Paul will benefit if one of them hits it big. You can read all about it in his next essay.&lt;&#x2F;p&gt;
&lt;p&gt;But maybe there’s another way.
Maybe it’s okay to have a small business with a loyal user base that pays the bills.
Maybe you don’t need to grow exponentially.&lt;&#x2F;p&gt;
&lt;p&gt;Maybe you can move slow and fix things instead.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Asking Better Questions</title>
        <published>2024-08-12T00:00:00+00:00</published>
        <updated>2024-08-13T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/asking-better-questions/"/>
        <id>https://endler.dev/2024/asking-better-questions/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/asking-better-questions/">&lt;p&gt;Recently, I realized that I mostly get paid to ask questions.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;&quot;&gt;As a consultant&lt;&#x2F;a&gt;, advising companies&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;podcast&#x2F;&quot;&gt;As a podcast host&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;openpodcast.app&#x2F;&quot;&gt;In calls with potential clients&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The curious thing is that, like most people in a similar position, I never had any formal training in asking questions!
I basically just wing it and try to get better over time.&lt;&#x2F;p&gt;
&lt;p&gt;That got me thinking: What makes a good question?&lt;br &#x2F;&gt;
The other day, I reflected on that. Here’s what I came up with.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-good-questions-are-open-ended&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#1-good-questions-are-open-ended&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;1. Good Questions Are Open-ended&lt;&#x2F;h2&gt;
&lt;p&gt;Recently, we did a survey about our podcast, and someone mentioned that some questions I asked the guests were “either-or” type of questions.&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Do you prefer dogs or cats?”&lt;br &#x2F;&gt;
A: “Dogs.”&lt;&#x2F;p&gt;
&lt;p&gt;Ouch, not a very interesting conversation!&lt;&#x2F;p&gt;
&lt;p&gt;A better one might have been “What’s your favorite pet?”.
It allows for surprising answers.&lt;&#x2F;p&gt;
&lt;p&gt;Q: “What’s your favorite pet?”&lt;br &#x2F;&gt;
A: “Tarantula!”&lt;&#x2F;p&gt;
&lt;p&gt;We have to ask ourselves what we want out of the answer,
which leads me to my second observation:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-never-ask-a-question-if-you-don-t-care-about-the-answer&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#2-never-ask-a-question-if-you-don-t-care-about-the-answer&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;2. Never Ask A Question If You Don’t Care About The Answer&lt;&#x2F;h2&gt;
&lt;p&gt;Or to rephrase it, “Only ask things you care about.”
If you don’t care about the other person’s answer, why even ask?
Ask something else you care about instead!&lt;&#x2F;p&gt;
&lt;p&gt;For example, when you ask someone if they prefer dogs or cats, what are you really asking?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Do you wonder if the person is &lt;em&gt;nice&lt;&#x2F;em&gt;?&lt;&#x2F;li&gt;
&lt;li&gt;Do you care about the logistics of owning a pet as a full-time employee?&lt;&#x2F;li&gt;
&lt;li&gt;Or do you rather want to hear a certain answer from the other person that happens to fit &lt;em&gt;your&lt;&#x2F;em&gt; narrative?
(The obvious correct answer is “cats”.)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Be honest!&lt;&#x2F;p&gt;
&lt;p&gt;Dig deeper into “why” you’re asking the question.
If it’s one of the former two questions, get straight to the point:&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Are you a nice person?”&lt;br &#x2F;&gt;
A: …&lt;&#x2F;p&gt;
&lt;p&gt;Q: “How do you manage having a pet if you have to work all day?”&lt;br &#x2F;&gt;
A: …&lt;&#x2F;p&gt;
&lt;p&gt;It will lead to better answers.&lt;&#x2F;p&gt;
&lt;p&gt;If it’s about your own agenda and you’re just looking for someone to give you the answer you’re hoping for (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Confirmation_bias&quot;&gt;confirmation bias&lt;&#x2F;a&gt;):
don’t. Again, allow them to surprise you!&lt;&#x2F;p&gt;
&lt;p&gt;Who knows? You might learn a thing or two about your preconceptions.&lt;&#x2F;p&gt;
&lt;p&gt;Which leads to…&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-good-questions-reveal-something-about-the-person-who-answers-bad-questions-about-the-person-who-asks&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#3-good-questions-reveal-something-about-the-person-who-answers-bad-questions-about-the-person-who-asks&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;3. Good Questions Reveal Something About The Person Who Answers; Bad Questions About The Person Who Asks&lt;&#x2F;h2&gt;
&lt;p&gt;It’s very easy to slip into a role where you’re framing people, and that lets your bias speak more about &lt;strong&gt;you&lt;&#x2F;strong&gt; than
the person you’re talking to.
Be conscious about that so that you can avoid it when it happens.&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Why do you love X?”&lt;br &#x2F;&gt;
A: “I don’t.”&lt;&#x2F;p&gt;
&lt;p&gt;Better:&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Tell me something you truly believe about X”&lt;br &#x2F;&gt;
A: “I believe that…”&lt;&#x2F;p&gt;
&lt;p&gt;The more unique the answer, the more you learn about the person.
So I would even say that a good question is one that reveals something &lt;em&gt;unique&lt;&#x2F;em&gt; about the person who answers.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What is it that only &lt;strong&gt;they&lt;&#x2F;strong&gt; can say?&lt;&#x2F;li&gt;
&lt;li&gt;What is it that they have &lt;strong&gt;unique&lt;&#x2F;strong&gt; insight into?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Q: “As an expert in X, who has been in the field for 20 years, what is one thing that people always get wrong about X?”&lt;br &#x2F;&gt;
A: “People always think that X is about Y, but it’s really about Z.”&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-good-questions-are-stacked-on-top-of-each-other&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#4-good-questions-are-stacked-on-top-of-each-other&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;4. Good Questions Are Stacked On Top Of Each Other&lt;&#x2F;h2&gt;
&lt;p&gt;Do you know the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Five_whys&quot;&gt;&lt;em&gt;Five Whys&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; technique?
It’s simple: Ask “why” five times to get to the root of the issue.&lt;&#x2F;p&gt;
&lt;p&gt;Q: Are you happy with your job?&lt;br &#x2F;&gt;
A: No.&lt;&#x2F;p&gt;
&lt;p&gt;Q: Why?&lt;br &#x2F;&gt;
A: It drains my energy.&lt;&#x2F;p&gt;
&lt;p&gt;Q: Why?&lt;br &#x2F;&gt;
A: I have to do boring things.&lt;&#x2F;p&gt;
&lt;p&gt;Q: Why?&lt;br &#x2F;&gt;
A: My boss thinks they must be done by &lt;em&gt;someone&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Q: Why?&lt;br &#x2F;&gt;
A: No one got around to automating them.&lt;&#x2F;p&gt;
&lt;p&gt;Q: Why?&lt;br &#x2F;&gt;
A: We don’t have the skills to automate boring tasks.&lt;&#x2F;p&gt;
&lt;p&gt;Aha! If they learn how to automate things, this might lead to better job happiness!
That’s insightful.&lt;&#x2F;p&gt;
&lt;p&gt;What’s nice is that it was a purely mechanical process.
With every step, we dug deeper into the underlying question.
At some point, the truth revealed itself.&lt;&#x2F;p&gt;
&lt;p&gt;I love this technique. Good questions are built on top of each other.
The questions themselves don’t have to be complicated. It can actually be the same question asked a few times in a row – even a child could do that.&lt;&#x2F;p&gt;
&lt;p&gt;In fact, they do. A lot!
This is how they learn about the world around them.&lt;&#x2F;p&gt;
&lt;p&gt;As grown-ups, we should not unlearn this technique.
“It’s rude to ask that.” “Don’t pry.” “Don’t be nosy.”&lt;&#x2F;p&gt;
&lt;p&gt;We should relearn it! Ask follow-up questions to get to the root of things.&lt;&#x2F;p&gt;
&lt;p&gt;But also!
Hold the other person accountable.&lt;&#x2F;p&gt;
&lt;p&gt;Q: “How can we fix poverty?”&lt;br &#x2F;&gt;
A: “I will do everything in my power to fix it.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “But how?”&lt;br &#x2F;&gt;
A: “I will try countermeasures which were discussed with…”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Can you give me a concrete example?”&lt;br &#x2F;&gt;
A: “…”&lt;&#x2F;p&gt;
&lt;p&gt;When someone answers your question, ask yourself if the answer really covered everything you wanted to know.
Often, the most interesting pieces are omitted. Sometimes on purpose. But this is the most revealing part,
the part at the verge of uncertainty and insecurity and you have to uncover it to get to the heart of the matter!
If you don’t do this, conversations stay shallow.&lt;&#x2F;p&gt;
&lt;p&gt;Speaking of which…&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-good-questions-run-deep&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#5-good-questions-run-deep&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;5. Good Questions Run Deep&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;“Why is the sky blue?”&lt;&#x2F;li&gt;
&lt;li&gt;“How do people fall in love?”&lt;&#x2F;li&gt;
&lt;li&gt;“Are you happy?”&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These are simple questions!
But they touch on the very foundation of what we know, our perception of the world, and ourselves.&lt;&#x2F;p&gt;
&lt;p&gt;The simpler the question, the deeper the answer.
Answering with “I don’t know” is totally fine.
The important part is to stay curious and to be genuinely interested in the answer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;6-let-the-winners-run-and-cut-your-losses-short&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#6-let-the-winners-run-and-cut-your-losses-short&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;6. Let The Winners Run And Cut Your Losses Short&lt;&#x2F;h2&gt;
&lt;p&gt;Sometimes, no matter what you try, there’s just nothing in a conversation.
You might have ended up in that weird space where people are simply out of their depth
and you turn circles.&lt;&#x2F;p&gt;
&lt;p&gt;Cut the cord.&lt;&#x2F;p&gt;
&lt;p&gt;Just acknowledge it and move on.&lt;&#x2F;p&gt;
&lt;p&gt;Trained conversationalists do it all the time without anyone noticing.
The conversation gets boring, so they just move on to the next topic.
There doesn’t even have to be a transition.&lt;&#x2F;p&gt;
&lt;p&gt;Q: “So, what do you do for a living?”&lt;br &#x2F;&gt;
A: “I’m a plumber.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Oh, interesting. So, what are your plans if you win?”&lt;br &#x2F;&gt;
A: …&lt;&#x2F;p&gt;
&lt;p&gt;Once you notice that, you will see it everywhere.
We do it all the time in our daily lives, too, for example on the phone.
Just cut your losses, move on to the next topic.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, if you notice that you both are really into a topic, just run with it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;7-give-people-space-to-think&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#7-give-people-space-to-think&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;7. Give People Space To Think&lt;&#x2F;h2&gt;
&lt;p&gt;Pauses are powerful.&lt;&#x2F;p&gt;
&lt;p&gt;Ask your question and then… wait. Just wait.&lt;&#x2F;p&gt;
&lt;p&gt;Don’t fill the silence with your own thoughts or insecurities.
Let the question speak for itself.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re truly interested in a deeper thought, you need to give people time to unpack it - for you and for themselves.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re not willing to wait, you’ll miss out on the best part of the conversation.&lt;&#x2F;p&gt;
&lt;p&gt;We are trained to give quick answers.
If someone asks you “How’s it going?”, the expected answer is “Good, you?”.
People are surprised when I take a moment to answer and give them a truly honest answer, which might be deeply personal.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, let people give you their quick answer first. Then wait.
Often, they will stop and follow up with a much more personal answer.&lt;&#x2F;p&gt;
&lt;p&gt;Use pauses to your advantage.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;8-obvious-questions-can-be-the-best-questions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#8-obvious-questions-can-be-the-best-questions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;8. Obvious Questions Can Be The Best Questions&lt;&#x2F;h2&gt;
&lt;p&gt;If you look close enough, which question to ask becomes obvious.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;“Why are we still working on this?”&lt;&#x2F;li&gt;
&lt;li&gt;“Should we split up?”&lt;&#x2F;li&gt;
&lt;li&gt;“How do you feel after the diagnosis?”&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;You’re addressing the elephant in the room!&lt;br &#x2F;&gt;
But just because you have an obvious question, that doesn’t make it easy to ask!&lt;&#x2F;p&gt;
&lt;p&gt;You might know that the question could hurt.
Or that the answer is uncomfortable to handle.
And yet, it’s still the right question to ask.&lt;&#x2F;p&gt;
&lt;p&gt;What I noticed is that oftentimes multiple people have the same “obvious” question in mind.
They are just too afraid to ask.&lt;&#x2F;p&gt;
&lt;p&gt;Most people dance around the topic because they want to be polite.
They don’t address problems head-on because it’s easier!
The result is small talk.&lt;&#x2F;p&gt;
&lt;p&gt;Especially if you get paid to ask questions, your job is to ask questions that no one else wants to ask.
Often, politics, infighting, and hidden agendas make it very hard for people to break out of their role and ask the obvious question.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re not afraid to ask the obvious question, you will look like Houdini.&lt;&#x2F;p&gt;
&lt;p&gt;Suddenly, an avalanche of follow-up questions gets unleashed.
An honest, constructive conversation emerges.&lt;&#x2F;p&gt;
&lt;p&gt;The thing is, just because you don’t ask the uncomfortable question, it doesn’t make the problem go away.
In fact, you might make it worse in the long run.
It’s easier to get it out of the way and move on!&lt;&#x2F;p&gt;
&lt;p&gt;Q: Why are we still working on this?&lt;br &#x2F;&gt;
A: Actually, I have no idea. Let’s find something else.&lt;&#x2F;p&gt;
&lt;p&gt;Q: Should we split up?&lt;br &#x2F;&gt;
A: Yes, I think so. Let’s talk about it.&lt;&#x2F;p&gt;
&lt;p&gt;Q: How do you feel after the diagnosis?&lt;br &#x2F;&gt;
A: I’m scared. I don’t know what to do. But I’m glad you asked.&lt;&#x2F;p&gt;
&lt;p&gt;The truth is hidden in plain sight.
If no one dares to ask, these questions stay unanswered.
The trick is to accept the answer for what it is.
Don’t be mad or angry at people who honestly answer your question.
Be mad or angry for not asking sooner.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;if-you-don-t-understand-the-answer-ask-again&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#if-you-don-t-understand-the-answer-ask-again&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;If You Don’t Understand The Answer, Ask Again&lt;&#x2F;h2&gt;
&lt;p&gt;In the past, I would often gloss over an answer and pretend I understood it.
Turns out that it was a bad strategy:
In the best case, I would have missed out on a great opportunity to learn something new.
In the worst case, I wouldn’t have a good question to follow up with.&lt;&#x2F;p&gt;
&lt;p&gt;Funnily, I’m rarely alone with this problem.
There’s usually more than one confused person in the room.
So don’t be afraid to refine your question to clarify any misunderstandings.&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Can you explain that differently?”&lt;br &#x2F;&gt;
A: …&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Am I correct in understanding that you mean…?”&lt;br &#x2F;&gt;
A: …&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Can you give me an example?”&lt;br &#x2F;&gt;
A: …&lt;&#x2F;p&gt;
&lt;p&gt;There’s an old Chinese proverb that goes like this:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;He who asks a question is a fool for five minutes; he who does not ask a question remains a fool forever.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;good-observations-yield-good-questions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#good-observations-yield-good-questions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Good Observations Yield Good Questions&lt;&#x2F;h2&gt;
&lt;p&gt;I noticed that many people who ask great questions have exceptional observation skills.
They notice things that others don’t.&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Why are you still working here?”&lt;br &#x2F;&gt;
A: “I need the money.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Tough luck. What’s for lunch?”&lt;br &#x2F;&gt;
A: …&lt;&#x2F;p&gt;
&lt;p&gt;vs.&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Why are you still working here?”&lt;br &#x2F;&gt;
A: “I need the money.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “I noticed that you have this book on your desk. What’s that about?”&lt;br &#x2F;&gt;
A: “Oh, that’s my passion! I’m reading up on sales because I want to start my own business.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “Nice! What is it about sales that you find so interesting?”&lt;br &#x2F;&gt;
A: …&lt;&#x2F;p&gt;
&lt;p&gt;See how this tiny observation about a book on the desk led to a much deeper conversation?
Suddenly, you’re talking about someone’s passion and dreams.
You might inspire them to have more conversations with customers during work time to get some practice.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to improve your observation skills, come prepared.
Learn more about the person you’re talking to.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;What are they passionate about?&lt;&#x2F;li&gt;
&lt;li&gt;Who’s their role model?&lt;&#x2F;li&gt;
&lt;li&gt;What are they doing in their free time?&lt;&#x2F;li&gt;
&lt;li&gt;What are they reading?&lt;&#x2F;li&gt;
&lt;li&gt;Which projects are they working on?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you come prepared, you’ll have an easier time asking good questions.
Context makes good questions obvious.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-best-follow-up-to-an-answer-is-a-question&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-best-follow-up-to-an-answer-is-a-question&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Best Follow-up To An Answer Is A Question&lt;&#x2F;h2&gt;
&lt;p&gt;Okay, you got an answer.
Now what?&lt;&#x2F;p&gt;
&lt;p&gt;Many people follow up with a statement about themselves.&lt;&#x2F;p&gt;
&lt;p&gt;“Oh, I also like that!”&lt;br &#x2F;&gt;
“Yes, I also did that!”&lt;br &#x2F;&gt;
“Let me tell you about my experience!”&lt;br &#x2F;&gt;
“You should do this!”&lt;&#x2F;p&gt;
&lt;p&gt;This shows that you’re not interested in the other person, only in yourself.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, what if you could only follow up with a question?&lt;&#x2F;p&gt;
&lt;p&gt;Q: “What’s your favorite sport?”&lt;br &#x2F;&gt;
A: “Table tennis.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “How did you get into that?”&lt;br &#x2F;&gt;
A: “My dad played it when I was young.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “What’s your favorite memory of playing table tennis with your dad?”&lt;br &#x2F;&gt;
A: “We used to play in the basement. It was so much fun!”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “What made it so much fun?”&lt;br &#x2F;&gt;
A: “I don’t know. It was just the two of us. It was our thing.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “What did you learn from your dad about table tennis?”&lt;br &#x2F;&gt;
A: “He taught me how to serve. He was really good at it.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “What’s the most important thing about serving in table tennis?”&lt;br &#x2F;&gt;
A: “You have to hit the ball at the right angle. Otherwise, it’s easy to return.”&lt;&#x2F;p&gt;
&lt;p&gt;Q: “What’s the most difficult angle to return?”&lt;br &#x2F;&gt;
A: “The one that goes straight to the corner. It’s hard to reach.”&lt;&#x2F;p&gt;
&lt;p&gt;See how this conversation unfolded?
It’s like peeling an onion.
You get deeper and deeper into the topic.
You learn more about the person.
You learn more about the topic.
Step by step, you tap into someone else’s hard-earned wisdom.
Look at all the things you learned in such a short time!
Their favorite sport, their childhood memories, their relationship with their dad, how to serve in table tennis, the most difficult angle to return a serve.
If you had followed up with “I like that too,” you would have missed out on all of this and probably never learned about it.&lt;&#x2F;p&gt;
&lt;p&gt;All just because we kept asking questions instead of making statements.&lt;&#x2F;p&gt;
&lt;p&gt;Think about all the people you know. Who do you like to talk to?
I bet it’s the people who ask you questions and listen to your answers instead of talking about themselves all the time.&lt;&#x2F;p&gt;
&lt;p&gt;Interestingly, it’s entirely selfish to ask questions.
You learn more about the other person than they learn about you.
You’re in control of the conversation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#summary&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;I’m still not good at asking questions.
I wrote this mostly as practice for myself.
Maybe it helps someone else too.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s a summary of what I wrote:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Good Questions Are Open-ended&lt;&#x2F;li&gt;
&lt;li&gt;Never Ask A Question If You Don’t Care About The Answer&lt;&#x2F;li&gt;
&lt;li&gt;Good Questions Reveal Something About The Person Who Answers; Bad Questions About The Person Who Asks&lt;&#x2F;li&gt;
&lt;li&gt;Good Questions Are Stacked On Top Of Each Other&lt;&#x2F;li&gt;
&lt;li&gt;Good Questions Run Deep&lt;&#x2F;li&gt;
&lt;li&gt;Let The Winners Run And Cut Your Losses Short&lt;&#x2F;li&gt;
&lt;li&gt;Give People Space To Think&lt;&#x2F;li&gt;
&lt;li&gt;Obvious Questions Can Be The Best Questions&lt;&#x2F;li&gt;
&lt;li&gt;If You Don’t Understand The Answer, Ask Again&lt;&#x2F;li&gt;
&lt;li&gt;Good Observations Yield Good Questions&lt;&#x2F;li&gt;
&lt;li&gt;The Best Follow-up To An Answer Is A Question&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Don’t be mistaken! Asking good questions is hard work!
You have to be present, you have to listen, you have to reflect.
It helps to take mental notes while you’re talking to someone.
After a while, you will get better at spotting the patterns.&lt;&#x2F;p&gt;
&lt;p&gt;Asking &lt;strong&gt;good&lt;&#x2F;strong&gt; questions is a skill that can be learned and improved upon.
Asking &lt;strong&gt;more&lt;&#x2F;strong&gt; questions can’t hurt along the way.&lt;&#x2F;p&gt;
&lt;p&gt;So, how do &lt;em&gt;you&lt;&#x2F;em&gt; ask better questions?&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Dying Web</title>
        <published>2024-08-08T00:00:00+00:00</published>
        <updated>2024-08-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/the-dying-web/"/>
        <id>https://endler.dev/2024/the-dying-web/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/the-dying-web/">&lt;p&gt;I look left and right, and I’m the only one who still uses Firefox.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;the-dying-web&amp;#x2F;travolta.gif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;the-dying-web&amp;#x2F;travolta.gif&quot; 
        

        

        
        
        
            width=&quot;426&quot;
        
        
            height=&quot;213&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;At conferences and in coworking spaces, it’s always the same scene: people using some flavor of Chrome.
Sometimes it’s Brave, sometimes Chromium, most of the time it’s just Google Chrome.&lt;&#x2F;p&gt;
&lt;p&gt;I find that hilariously appalling.&lt;&#x2F;p&gt;
&lt;p&gt;An entire generation grew up with access to great free tools and open standards, which helped them jumpstart their careers and
gave them access to excellent technology for free.&lt;&#x2F;p&gt;
&lt;p&gt;Now, the world’s largest websites are owned by the same company, which also owns the world’s most popular browser and
search engine. Coincidentally, they are also the world’s largest advertising company.
And people are wondering why they can’t block ads on YouTube anymore.&lt;&#x2F;p&gt;
&lt;p&gt;We gave it all away for nothing.&lt;&#x2F;p&gt;
&lt;p&gt;Let me be the first to admit that I too am not without sin.
There was a weak moment about 15 years ago when browser performance became so unbearable on anything other than Chrome
that it forced my hand to make the switch.
And yes, for a while, life was good and websites loaded quickly.&lt;&#x2F;p&gt;
&lt;p&gt;Reluctantly, I made the switch back to Firefox after a while, because open standards and privacy were
more important than a few milliseconds of loading time.
I could still understand why people would use Chrome, but I was happy with my choice.&lt;&#x2F;p&gt;
&lt;p&gt;Then &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.mozilla.org&#x2F;en&#x2F;mozilla&#x2F;introducing-firefox-quantum&#x2F;&quot;&gt;Firefox Quantum&lt;&#x2F;a&gt; came around, and I
told all my fellow developer friends about it.
To me, it was the best browser on the market, and I was proud to be a Firefox user again.
It was fast, snappy, and had a great add-on ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;To my surprise, nobody cared.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bad-habits-die-hard&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bad-habits-die-hard&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Bad Habits Die Hard&lt;&#x2F;h2&gt;
&lt;p&gt;Maybe people stayed with Chrome out of habit.&lt;&#x2F;p&gt;
&lt;p&gt;Performance and privacy aside, I just don’t know how people can cope with Chrome’s limited customizability.
It’s hilarious to watch people with 200 tabs named “G”, “Y”, or “X” struggle to find that one document they opened a week ago.&lt;&#x2F;p&gt;
&lt;p&gt;In comparison, vertical tabs on Firefox with add-ons like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;addons.mozilla.org&#x2F;en-US&#x2F;firefox&#x2F;addon&#x2F;sidebery&#x2F;&quot;&gt;Sidebery&lt;&#x2F;a&gt;
make Chrome look like a toy.&lt;&#x2F;p&gt;
&lt;p&gt;Anyhow, Chrome.&lt;&#x2F;p&gt;
&lt;p&gt;There was a time when I tried to educate people on the negative effects of browser monoculture.
Okay, my mum didn’t get it, but I was more disappointed by my fellow devs.
Everyone took the easy route and happily stayed on Uncle Google’s lap.&lt;&#x2F;p&gt;
&lt;p&gt;At this point, I neither have the willpower nor the energy to fight back;
it’s hopeless. It’s probably easier to get blood from a stone
than to convince someone to switch back to Firefox.
It’s so easy to switch, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;support.mozilla.org&#x2F;en-US&#x2F;kb&#x2F;switching-chrome-firefox&quot;&gt;you won’t even lose any open tabs&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;the-dying-web&amp;#x2F;marketshare.png&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;the-dying-web&amp;#x2F;marketshare.png&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;599&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;nobody-forces-you-to-use-chrome&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#nobody-forces-you-to-use-chrome&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Nobody Forces You to Use Chrome&lt;&#x2F;h2&gt;
&lt;p&gt;True, but the issues don’t stop at my front door.
As an outsider, I need to live with the consequences of browser monoculture every day.&lt;&#x2F;p&gt;
&lt;p&gt;Quite a few websites are unusable by now because they got “optimized for Chrome.”
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;webcompat&#x2F;web-bugs&#x2F;issues&#x2F;25070#issuecomment-460721700&quot;&gt;Microsoft Teams&lt;&#x2F;a&gt;, for example,
and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;webcompat&#x2F;web-bugs&#x2F;issues?q=is%3Aopen+is%3Aissue+label%3Abrowser-firefox&quot;&gt;the list is long&lt;&#x2F;a&gt;.
These websites fail for no good reason.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;del&gt;There are positive examples, too.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zencastr.com&#x2F;&quot;&gt;Zencastr&lt;&#x2F;a&gt;, for example, used to be broken on Firefox, but they fixed it.&lt;&#x2F;del&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Update: Zencastr is still broken on Firefox.&lt;&#x2F;strong&gt;
Thanks to Randell from Mozilla for pointing that out. Their &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;support.zencastr.com&#x2F;en&#x2F;articles&#x2F;5018334-system-requirements&quot;&gt;support page states that Chrome, Edge, or Brave are required&lt;&#x2F;a&gt;. They stopped supporting Firefox in February 2021 as per &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.zencastr.com&#x2F;blog&#x2F;2021&#x2F;2&#x2F;16&#x2F;zencastr-is-launching-video-recording-into-open-beta&quot;&gt;this blog post&lt;&#x2F;a&gt;. There’s an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bugzilla.mozilla.org&#x2F;show_bug.cgi?id=1899831&quot;&gt;open ticket in the Mozilla Bugzilla&lt;&#x2F;a&gt; tracking this issue. It’s currently blocked on some other issues, but there’s progress being made. The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.mozilla.org&#x2F;en-US&#x2F;docs&#x2F;Web&#x2F;API&#x2F;WebCodecs_API&quot;&gt;WebCodecs API&lt;&#x2F;a&gt;, which might be related to this problem, is currently in beta and progressing through Mozilla’s release process. While it’s disappointing that Zencastr doesn’t work on Firefox yet, it’s encouraging to see that Mozilla is actively working on resolving the underlying issues.&lt;&#x2F;p&gt;
&lt;p&gt;I also use Chrome for online calls, because tools like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;meet.jit.si&#x2F;&quot;&gt;Jitsi&lt;&#x2F;a&gt; don’t work well on Firefox.
Maybe it’s because of Firefox’s WebRTC support? Or, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.mozilla.org&#x2F;webrtc&#x2F;&quot;&gt;maybe it’s because of Chrome&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Pop Quiz&lt;&#x2F;strong&gt;: If a website wants to play out of different speakers on your system, what permission must it have?&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Speaker-selection permission&lt;&#x2F;li&gt;
&lt;li&gt;Microphone permission&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;If you answered 2, then chances are you know your WebRTC stuff well, but you’re probably on a Chromium browser.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;how-could-google-get-free-rein&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#how-could-google-get-free-rein&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;How could Google get free rein?&lt;&#x2F;h2&gt;
&lt;p&gt;Because everyone and their car stopped testing their stuff anywhere else.
If everyone tweaks their site for Chrome, well, of course the site will work just fine on Chrome!
We find ways around Chrome’s weird quirks.
More users join the bandwagon because stuff “just works” and the vicious cycle continues.
I can’t blame them.
It’s easier to ride a horse in the direction it is going.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-at-what-cost&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#but-at-what-cost&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;But at what cost?&lt;&#x2F;h2&gt;
&lt;p&gt;*Elrond voice*: We’ve been down this road before. (Okay, I was there.)
We called it the &lt;em&gt;Browser Wars&lt;&#x2F;em&gt;: Netscape vs Internet Explorer. Netscape lost and Microsoft ruled over the web with an iron fist. It wasn’t fun.
We had more hacks around browser limitations than actual website functionality. Parents put their kids through college by working around browser bugs for money.&lt;&#x2F;p&gt;
&lt;p&gt;Microsoft tried &lt;em&gt;really&lt;&#x2F;em&gt; hard to make life as miserable as possible for everybody:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Internet Explorer has introduced an array of proprietary extensions to many of the standards, including HTML, CSS, and the DOM. This has resulted in several web pages that appear broken in standards-compliant web browsers and has introduced the need for a “quirks mode” to allow for rendering improper elements meant for Internet Explorer in these other browsers. — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Internet_Explorer&quot;&gt;Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Essentially, they broke the web and we all warmed our hands on the dumpster fire.
All we got in return was quirks mode.&lt;&#x2F;p&gt;
&lt;p&gt;Google is smarter! They break the web, too, but they make you stand inside the fire.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-should-i-care-about-a-browser-they-are-all-the-same-anyways&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-should-i-care-about-a-browser-they-are-all-the-same-anyways&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Why should I care about a browser? They are all the same anyways.&lt;&#x2F;h2&gt;
&lt;p&gt;…says the developer who gets &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.forbes.com&#x2F;sites&#x2F;zakdoffman&#x2F;2024&#x2F;06&#x2F;16&#x2F;google-chrome-tracking-on-windows-android-iphone-for-200-more-days&#x2F;&quot;&gt;tracked by Google&lt;&#x2F;a&gt;
every waking moment.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;the-dying-web&amp;#x2F;incognito.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;the-dying-web&amp;#x2F;incognito.jpg&quot; 
        
            alt=&quot;https:&amp;#x2F;&amp;#x2F;www.skeletonclaw.com&amp;#x2F;image&amp;#x2F;710734055173472257&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;397&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: https:&#x2F;&#x2F;www.skeletonclaw.com&#x2F;image&#x2F;710734055173472257
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;You see, Chrome is reeeeally good at marketing.
They say all the right things: We’re fast! We’re open source! We have the latest features!
What they don’t tell you is that they control the narrative of the World Wide Web.
They make you feel &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;browsers&#x2F;comments&#x2F;1810egw&#x2F;google_chrome_will_limit_ad_blockers_starting&#x2F;&quot;&gt;guilty for using adblockers&lt;&#x2F;a&gt; and add weird
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;v4.chriskrycho.com&#x2F;2017&#x2F;chrome-is-not-the-standard.html&quot;&gt;nonstandard browser features&lt;&#x2F;a&gt; because they can.
Lately, the uBlock Origin team just threw in the towel and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.theregister.com&#x2F;2024&#x2F;08&#x2F;06&#x2F;chrome_web_store_warns_end&#x2F;&quot;&gt;stopped supporting Chrome&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;But did anyone decide to jump ship?
I get the feeling that by now people turn a blind eye to Google’s evil practices.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;but-shouldn-t-brave-edge-opera-or-vivaldi-be-sufficient&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#but-shouldn-t-brave-edge-opera-or-vivaldi-be-sufficient&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;But shouldn’t Brave, Edge, Opera, or Vivaldi be sufficient?&lt;&#x2F;h2&gt;
&lt;p&gt;Unfortunately not. They all use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.chromium.org&#x2F;blink&#x2F;&quot;&gt;same browser engine&lt;&#x2F;a&gt; under the hood.
Browser makers make mistakes, so this engine is not perfect.
If it contains a bug and there’s no competition, that bug becomes the standard.
Alternative browser engines need to implement the bug as well to support websites which depend on it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-use-safari&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#i-use-safari&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;I Use Safari&lt;&#x2F;h2&gt;
&lt;p&gt;Congratulations, you switched from a browser controlled by a 2 trillion dollar company to a browser controlled by a 3 trillion dollar company. Oh, and it doesn’t run on Windows or Linux.
Both Apple and Google would throw you under the bus if it made them more profit.
Oh, and did you know that Google paid Apple &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.pymnts.com&#x2F;antitrust&#x2F;2024&#x2F;google-ruling-may-blunt-apple-services-revenue-ecosystem-growth&#x2F;&quot;&gt;20 billion dollars in 2022&lt;&#x2F;a&gt; to be the default search engine on Safari?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-can-i-do&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-can-i-do&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;What Can I Do?&lt;&#x2F;h2&gt;
&lt;p&gt;If you’ve made it this far, do yourself a favor and spend a few minutes trying Firefox.
Who knows? You might just like it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.mozilla.org&#x2F;firefox&quot;&gt;Try Firefox today,&lt;&#x2F;a&gt; please?&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How To Sell To Developers</title>
        <published>2024-05-27T00:00:00+00:00</published>
        <updated>2024-05-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2024/selling-to-developers/"/>
        <id>https://endler.dev/2024/selling-to-developers/</id>
        
        <content type="html" xml:base="https://endler.dev/2024/selling-to-developers/">&lt;p&gt;One of the hardest challenges I know is how to sell to developers.&lt;&#x2F;p&gt;
&lt;p&gt;This is NOT an article for developers. Today, I want to write for non-developers whose job it is to sell to developers. My goal is to help you understand how they think.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;developers-hate-being-sold-to&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#developers-hate-being-sold-to&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Developers Hate Being Sold To&lt;&#x2F;h2&gt;
&lt;p&gt;We tend to be a skeptical bunch! We’re not reachable through Google ads because we use ad blockers. We expect software to be free and open source, so we don’t usually pay for it. We subscribe to a handful of services that provide a lot of value for very little cost. Everything else we build ourselves. See the problem?&lt;&#x2F;p&gt;
&lt;p&gt;How do you &lt;em&gt;sell&lt;&#x2F;em&gt; to these people?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-developer-s-dilemma&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-developer-s-dilemma&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Developer’s Dilemma&lt;&#x2F;h2&gt;
&lt;p&gt;Strangely enough, when developers think about starting a business, the first products they consider are often those aimed at other developers, despite there being many easier markets to sell to! We love building things so much that we try to sell the things we build to people just like us.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s my advice:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Don’t build a product for developers.&lt;&#x2F;li&gt;
&lt;li&gt;Seriously, don’t build a product for developers.&lt;&#x2F;li&gt;
&lt;li&gt;Since you’ll likely ignore the first two pieces of advice, at least learn how to market to developers effectively.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;what-you-need-to-know-about-marketing-to-developers&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-you-need-to-know-about-marketing-to-developers&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;What You Need to Know About Marketing to Developers&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s the bitter truth. To sell to developers…&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;You will have to be present in the places where they hang out.&lt;&#x2F;li&gt;
&lt;li&gt;You will have to invest a lot of time in community building.&lt;&#x2F;li&gt;
&lt;li&gt;You will have to be extremely patient.&lt;&#x2F;li&gt;
&lt;li&gt;There is no shortcut.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;What if you don’t have the time or the patience? See rule 1 above.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-developer-product-journey-so-far&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#my-developer-product-journey-so-far&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;My Developer Product Journey So Far&lt;&#x2F;h2&gt;
&lt;p&gt;You might ask, “Why should I listen to you? Have you ever sold a product to developers?”&lt;&#x2F;p&gt;
&lt;p&gt;I’ll let you be the judge of that. Here are a few products that I have built and sold to developers:&lt;&#x2F;p&gt;
&lt;h3 id=&quot;codeprints&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#codeprints&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codeprints.dev&#x2F;&quot;&gt;codeprints&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;selling-to-developers&amp;#x2F;codeprints.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;selling-to-developers&amp;#x2F;codeprints.jpg&quot; 
        
            alt=&quot;Homepage of CodePrints with my GitHub profile as a print&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;411&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Homepage of CodePrints with my GitHub profile as a print
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;This was a fun experiment during the pandemic. We sold posters of GitHub timelines. Our marketing strategy included posts on Reddit and Hacker News, and we sent free prints to a few “devfluencers.” The novelty effect and viral marketing worked well. Eventually, we sold the company to a developer agency because we didn’t want to deal with the logistics.&lt;&#x2F;p&gt;
&lt;p&gt;Read more about CodePrints in &lt;a href=&quot;&#x2F;2021&#x2F;codeprints&#x2F;&quot;&gt;this blog post&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;lychee&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#lychee&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lychee.cli.rs&#x2F;&quot;&gt;Lychee&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;selling-to-developers&amp;#x2F;lychee.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;selling-to-developers&amp;#x2F;lychee.jpg&quot; 
        
            alt=&quot;Homepage of Lychee&amp;#x27;s documentation page&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;435&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Homepage of Lychee’s documentation page
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;I built this tool for myself because I needed it. Lychee is a command-line tool that checks for broken links in markdown and HTML files. It has become quite popular on GitHub, with companies like Google and Amazon using it. However, I’ve never made any money from it. I reached out to some companies to sponsor the project, but it was very hard to get a response or explain why they should sponsor a free tool.&lt;&#x2F;p&gt;
&lt;p&gt;I wrote about &lt;a href=&quot;&#x2F;2021&#x2F;oss-money&#x2F;&quot;&gt;making money with Open Source here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;analysis-tools&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#analysis-tools&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;analysis-tools.dev&#x2F;&quot;&gt;Analysis Tools&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;selling-to-developers&amp;#x2F;analysis-tools-homepage.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;selling-to-developers&amp;#x2F;analysis-tools-homepage.jpg&quot; 
        
            alt=&quot;Homepage of analysis-tools.dev&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;436&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Homepage of analysis-tools.dev
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;This is a directory of tools for developers. It’s a side project that I started in 2015 (did I mention you need to be patient?), and it has grown to be a popular resource. Together with two friends, we sell sponsorships and ads on the site, which provides a nice side income.&lt;&#x2F;p&gt;
&lt;p&gt;I think this project works because it’s not a product for developers but &lt;strong&gt;a product for people who build products for developers&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Our customers are mostly developer advocates, developer relations folks, and marketing people who want to reach developers.&lt;&#x2F;p&gt;
&lt;p&gt;Sponsoring on Analysis Tools is &lt;strong&gt;extremely cheap&lt;&#x2F;strong&gt; compared to other marketing channels like Google ads. On Google, you can easily spend thousands of dollars per month trying to reach developers.&lt;&#x2F;p&gt;
&lt;p&gt;On Analysis Tools, you can reach them for a fraction of that cost. The basic tier is $100 per month, and for that, you get your logo on the site and in every repo. Thousands of developers visit the site every month. It’s basically a no-brainer to sponsor the site if you build a linter, a static code analyzer, or any other tool that developers use.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;selling-to-developers&amp;#x2F;analysis-tools-list.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2024&amp;#x2F;selling-to-developers&amp;#x2F;analysis-tools-list.jpg&quot; 
        
            alt=&quot;Tools page of analysis-tools.dev&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;436&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Tools page of analysis-tools.dev
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Think of it this way: when was the last time these companies had the chance to reach thousands of developers for $100? What is the total cost of acquisition for a developer? How much would you pay for a developer to try out your tool?&lt;&#x2F;p&gt;
&lt;p&gt;And still…&lt;&#x2F;p&gt;
&lt;h3 id=&quot;only-20-of-companies-immediately-get-it&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#only-20-of-companies-immediately-get-it&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Only 20% Of Companies Immediately Get It&lt;&#x2F;h3&gt;
&lt;p&gt;From the companies I’ve talked to, only around 20% get it immediately. There are perhaps 30% that need a little handholding. The other 50% see it as an ad placement and want to know the click-through rate.&lt;&#x2F;p&gt;
&lt;p&gt;Let me repeat: It’s not about the click-through rate. It’s about the branding and the reach.&lt;&#x2F;p&gt;
&lt;p&gt;You will never reach a critical audience if you don’t start investing in the developer community. This is not a one-time thing. You need a lot of exposure until you get noticed and developers start talking about your product. &lt;strong&gt;If you try to fake it, you won’t get far. Devs will avoid your product like the plague and tell their friends to do the same.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Your main constraint is the attention of developers!&lt;&#x2F;p&gt;
&lt;p&gt;These folks constantly get bombarded with millions of products and don’t have time to evaluate them all. They stopped actively looking for new tools a long time ago. They rely on a handful of trusted sources they follow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-trust-is-the-only-way&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#building-trust-is-the-only-way&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Building Trust Is The Only Way&lt;&#x2F;h2&gt;
&lt;p&gt;Getting into their circle of trust is hard, and for that reason, you need to be patient and invest a lot of time into relationship building. If you can afford it, hire a developer advocate. A good one is heavily invested in open source and knows how to write for developers.
At the very least, you need to be present in the places where developers hang out. So reach out to open source maintainers in your niche and see if you can collaborate or sponsor their projects. Don’t waste cash on Google ads or other traditional marketing channels. Go where the developers are.&lt;&#x2F;p&gt;
&lt;p&gt;I hope this article helped someone who is struggling to sell to developers. Perhaps one of you will reach out to some open source maintainers in their niche and sponsor their projects. That would be a great outcome!&lt;&#x2F;p&gt;
&lt;p&gt;There’s a plus side to all of this: once you understand that you need to invest in the developer community, you will have a competitive advantage because most other companies don’t get it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Cursed Rust: Printing Things The Wrong Way</title>
        <published>2023-11-01T00:00:00+00:00</published>
        <updated>2023-11-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2023/cursed-rust/"/>
        <id>https://endler.dev/2023/cursed-rust/</id>
        
        <content type="html" xml:base="https://endler.dev/2023/cursed-rust/">&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;qwOlWfYlq0A&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;maxresdefault.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;maxresdefault.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;p&gt;There is a famous story about a physicist during an exam at the University of
Copenhagen. The candidate was asked to describe how to determine a skyscraper’s
height using a barometer. The student suggested dangling the barometer from the
building’s roof using a string and then measuring the length of the string plus
the barometer’s height. Although technically correct, the examiners were not
amused.&lt;&#x2F;p&gt;
&lt;p&gt;After a complaint and a reevaluation, the student offered various physics-based
solutions, ranging from dropping the barometer and calculating the building’s
height using the time of fall, to using the proportion between the lengths of
the building’s shadow and that of the barometer to calculate the building’s
height from the height of the barometer.
He even humorously suggested simply asking the caretaker in exchange for the
barometer.&lt;&#x2F;p&gt;
&lt;p&gt;The physicist, as the legend goes, was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Niels_Bohr&quot;&gt;Niels Bohr&lt;&#x2F;a&gt;, who
went on to receive a Nobel Prize in 1922. This story is also known as the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Barometer_question&quot;&gt;barometer question&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-is-this-story-interesting&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-is-this-story-interesting&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Why Is This Story Interesting?&lt;&#x2F;h2&gt;
&lt;p&gt;The question and its possible answers have an important didactic side effect:
they convey to the learner that one can also get to the solution with unconventional
methods — and that these methods are often more interesting than the
canonical solution &lt;em&gt;because they reveal something about the problem itself&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There is virtue in learning from unconventional answers to conventional questions.
To some extent, this fosters new ways of thinking and problem-solving, which is
an essential part of innovation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;applying-the-same-principle-to-learning-rust&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#applying-the-same-principle-to-learning-rust&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Applying The Same Principle To Learning Rust&lt;&#x2F;h2&gt;
&lt;p&gt;One of the first examples in any book on learning Rust is the “Hello, world!”
program.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It’s an easy way to test that your Rust installation is working correctly.&lt;&#x2F;p&gt;
&lt;p&gt;However, we can also have some fun and turn the task on its head:
let’s find ways to print “Hello, world!” without using &lt;code&gt;println!&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s try to come up with as many unconventional solutions as possible.
The weirder, the better! As you go through each of the solutions
below, try to understand &lt;em&gt;why&lt;&#x2F;em&gt; they work and what you can learn from them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rustjerk&#x2F;comments&#x2F;16xty71&#x2F;s_str_print_shello&#x2F;&quot;&gt;This started as a meme&lt;&#x2F;a&gt;,
but I decided to turn it into a full article after the post got a lot of
attention.&lt;&#x2F;p&gt;
&lt;p&gt;It goes without saying that you should never use any of these solutions in
production code. Check out this &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mTvare6&#x2F;hello-world.rs&quot;&gt;enterprise-ready version of
hello world&lt;&#x2F;a&gt; instead.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-1-desugaring-println&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-1-desugaring-println&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 1: Desugaring &lt;code&gt;println!&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;write!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This solution is interesting, because it shows that &lt;code&gt;println!&lt;&#x2F;code&gt; is just a macro that
expands to a call to &lt;code&gt;write!&lt;&#x2F;code&gt; with a newline character appended to the string.&lt;&#x2F;p&gt;
&lt;p&gt;The real code is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust&#x2F;blob&#x2F;f3457dbf84cd86d284454d12705861398ece76c3&#x2F;library&#x2F;std&#x2F;src&#x2F;io&#x2F;stdio.rs#L1097&quot;&gt;much weirder&lt;&#x2F;a&gt;. Search for &lt;code&gt;print&lt;&#x2F;code&gt; in this file if you want to be amazed.
&lt;code&gt;write!&lt;&#x2F;code&gt; itself &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fmt&#x2F;trait.Write.html#method.write_fmt&quot;&gt;desugars to a call to &lt;code&gt;write_fmt&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;, which is a method of the &lt;code&gt;Write&lt;&#x2F;code&gt; trait.&lt;&#x2F;p&gt;
&lt;p&gt;There is a real-world use case for this: if you want to print things really fast, you can
lock &lt;code&gt;stdout&lt;&#x2F;code&gt; once and then use &lt;code&gt;write!&lt;&#x2F;code&gt;. This avoids the overhead
of locking &lt;code&gt;stdout&lt;&#x2F;code&gt; for each call to &lt;code&gt;println!&lt;&#x2F;code&gt;. See &lt;a href=&quot;&#x2F;2017&#x2F;yes&#x2F;&quot;&gt;this article on how to write a very
fast version of &lt;code&gt;yes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; with this trick.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-2-iterating-over-characters&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-2-iterating-over-characters&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 2: Iterating Over Characters&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; print!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; c&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This shows that you can implement &lt;code&gt;println!&lt;&#x2F;code&gt; using Rust’s powerful iterators.
Here we iterate over the characters of the string and print each one of them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;code&gt;chars()&lt;&#x2F;code&gt; returns an iterator over &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;primitive.char.html&quot;&gt;Unicode scalar values&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Learn more about iterators &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-3-impl-display&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-3-impl-display&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 3: Impl &lt;code&gt;Display&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; HelloWorld&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Display&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; HelloWorld&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Formatter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        write!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;HelloWorld&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This teaches us a little bit about how traits work in Rust: We define a struct
that implements the &lt;code&gt;Display&lt;&#x2F;code&gt; trait, which allows us to print it using &lt;code&gt;print!&lt;&#x2F;code&gt;.
In general, &lt;code&gt;Display&lt;&#x2F;code&gt; is intended to make more complex types printable, but it
is also possible to implement it for a hardcoded string!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-4-who-needs-display&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-4-who-needs-display&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 4: Who Needs &lt;code&gt;Display&lt;&#x2F;code&gt;?&lt;&#x2F;h2&gt;
&lt;p&gt;How about we create our own trait instead of using &lt;code&gt;Display&lt;&#x2F;code&gt;?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Println&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; println&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Println&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; println&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        print!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;println&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can exploit the fact that we can name our trait methods however we want. In
this example, we choose &lt;code&gt;println&lt;&#x2F;code&gt;, making it look like it is part of the
standard library.&lt;&#x2F;p&gt;
&lt;p&gt;This completely turns the &lt;code&gt;println!&lt;&#x2F;code&gt; macro on its head. Instead of
passing a string as an argument, we call a method on the string itself!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-5-who-needs-println-when-you-got-panic&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-5-who-needs-println-when-you-got-panic&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 5: Who Needs &lt;code&gt;println!&lt;&#x2F;code&gt; When You Got &lt;code&gt;panic!&lt;&#x2F;code&gt;?&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;panic!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There are other ways to print things in Rust than using &lt;code&gt;println!&lt;&#x2F;code&gt;. In this
case, we use &lt;code&gt;panic!&lt;&#x2F;code&gt;, which prints the string (as a side-effect) and
immediately terminates the program. It works as long as we only want to print
a single string…&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-6-i-hearts-closures&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-6-i-hearts-closures&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 6: I ♥︎️ Closures&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; print!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; s&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Rust allows you to call a closure directly after its
definition. The closure is defined as an anonymous function that takes a
string slice as an argument and prints it. The string slice is passed as an
argument to the closure.&lt;&#x2F;p&gt;
&lt;p&gt;In practice, this can be useful for defining a closure that is only used once
and for which you don’t want to come up with a name.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-7-c-style&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-7-c-style&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 7: C Style&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;c_char&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; c_int&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; core&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;ffi&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;CStr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;C&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; printf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; c_char&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ...&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; c_int&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; HI&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;CStr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; CStr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_bytes_until_nul&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;        Err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; panic!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        printf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;HI&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;as_ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You don’t even need to use Rust’s standard library to print things! This
example shows how to call the C standard library’s &lt;code&gt;printf&lt;&#x2F;code&gt; function from Rust.
It’s unsafe because we are using a raw pointer to pass the string to the
function. This teaches us a little bit about how FFI works in Rust.&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rustjerk&#x2F;comments&#x2F;16xty71&#x2F;s_str_print_shello&#x2F;k36n6be&#x2F;&quot;&gt;&#x2F;u&#x2F;pinespear on Reddit&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;infosec.exchange&#x2F;@brk&quot;&gt;@brk@infosec.exchange&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-8-c-style&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-8-c-style&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 8: C++ Style&lt;&#x2F;h2&gt;
&lt;p&gt;We’re well into psychopath territory now… so let’s not stop here.
If you try extremely hard, you can bend Rust to your will and make it look
like C++.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;ops&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Shl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;allow&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;non_camel_case_types&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; cout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;allow&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;non_camel_case_types&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; endl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Shl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; cout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; cout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; shl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        print!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        cout&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Shl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;endl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; cout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    type&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; shl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; endl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; Self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Output&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;cout&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello World&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; endl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;Shl&lt;&#x2F;code&gt; trait is used to implement the &lt;code&gt;&amp;lt;&amp;lt;&lt;&#x2F;code&gt; operator. The &lt;code&gt;cout&lt;&#x2F;code&gt;
struct implements &lt;code&gt;Shl&lt;&#x2F;code&gt; for any type that implements &lt;code&gt;Display&lt;&#x2F;code&gt;, which allows
us to print any printable type. The &lt;code&gt;endl&lt;&#x2F;code&gt; struct implements &lt;code&gt;Shl&lt;&#x2F;code&gt; for &lt;code&gt;cout&lt;&#x2F;code&gt;,
which prints the newline character in the end.&lt;&#x2F;p&gt;
&lt;p&gt;Credit goes to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wisha.page&#x2F;posts&#x2F;fun-rust-operators&#x2F;&quot;&gt;Wisha Wanichwecharungruang&lt;&#x2F;a&gt; for this
solution.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-9-unadulterated-control-with-assembly&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-9-unadulterated-control-with-assembly&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 9: Unadulterated Control With Assembly&lt;&#x2F;h2&gt;
&lt;p&gt;All of these high-level abstractions stand in the way of printing things
efficiently. We have to take back control of your CPU. Assembly is the way. No more wasted cycles.
No hidden instructions. Pure, unadulterated performance.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;arch&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;asm&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; SYS_WRITE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; STDOUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;cfg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;not&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;target_arch &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;x86_64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    panic!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;This only works on x86_64 machines!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bytes_written&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    unsafe&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        asm!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;            &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;syscall&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            inout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rax&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; SYS_WRITE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bytes_written&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            inout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rdi&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; STDOUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            in&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rsi&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;as_ptr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            in&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rdx&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;            &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; syscall clobbers these&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rcx&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r11&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    assert_eq!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;bytes_written&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?version=stable&amp;amp;mode=release&amp;amp;edition=2021&amp;amp;gist=d11b1f6ef0711681e1f5a613e5cf412b&quot;&gt;Rust Playground&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;If you’re wondering why we use Rust in the first place if all
we do is call assembly code, you’re missing the point!
This is about way more than just printing things.
It is about freedom! Don’t tell me how I should use my CPU.&lt;&#x2F;p&gt;
&lt;p&gt;Okaaay, it only works on x86_64 machines, but that’s a small sacrifice to make
for freedom.&lt;&#x2F;p&gt;
&lt;p&gt;Submitted by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;isaacthefallenapple&quot;&gt;isaacthefallenapple&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;solution-10-blazing-fast&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#solution-10-blazing-fast&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Solution 10: “Blazing Fast”&lt;&#x2F;h2&gt;
&lt;p&gt;Why did we pay a premium for all those CPU cores if we aren’t actually using
them? Wasn’t fearless concurrency one of Rust’s promises? Let’s put those cores
to good use!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;sync&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Arc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Mutex&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Mutex&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; handles&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Arc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;clone&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;spawn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;move&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;            thread&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sleep&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_millis&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            print!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; phrase&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        handles&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; handles&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;join&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here, each character is printed in a separate thread. The threads are spawned
in a loop, and each thread sleeps for a certain amount of milliseconds before
printing its character. This uses the full power of your CPU to print a string!
It might not always consistently print the characters in the right order (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;people.ece.ubc.ca&#x2F;sasha&#x2F;papers&#x2F;eurosys16-final29.pdf&quot;&gt;hey, scheduling
is hard!&lt;&#x2F;a&gt;), but
that’s a worthwhile trade-off for all the raw performance gains.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;your-turn&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#your-turn&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Your Turn!&lt;&#x2F;h2&gt;
&lt;p&gt;If you’ve got more solutions, please send me a message.&lt;&#x2F;p&gt;
&lt;p&gt;Also, if you liked this article, you might also enjoy the yearly obfuscated C
code contest. Check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ioccc.org&#x2F;years.html&quot;&gt;previous winners here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you were actually more intrigued by the barometer story, read &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.goodreads.com&#x2F;book&#x2F;show&#x2F;35167685-surely-you-re-joking-mr-feynman&quot;&gt;Surely You’re
Joking, Mr.
Feynman!&lt;&#x2F;a&gt;,
a book by Richard Feynman, another famous physicist and Nobel Prize winner, who
was known for his unconventional way of thinking.&lt;&#x2F;p&gt;
&lt;p&gt;We should all strive to think outside the box and come up with unconventional
solutions to problems. Who knows, maybe that’s the key to a deeper
understanding of the problem itself?&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Deploy Rust Code Faster</title>
        <published>2023-10-25T00:00:00+00:00</published>
        <updated>2023-10-25T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2023/move-fast-rust/"/>
        <id>https://endler.dev/2023/move-fast-rust/</id>
        
        <content type="html" xml:base="https://endler.dev/2023/move-fast-rust/">&lt;p&gt;I’ve come a long way in my tech journey, from dealing with bare metal servers to
exploring the world of cloud computing. Initially, it seemed so straightforward
– spin up a server, deploy a container, and you’re done. But as I delved deeper,
I realized that the ease of infrastructure is not as simple as it appears.&lt;&#x2F;p&gt;
&lt;p&gt;Cloud providers offer a multitude of tools, each with its own learning curve:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Google Cloud &#x2F; AWS&lt;&#x2F;li&gt;
&lt;li&gt;Kubernetes&lt;&#x2F;li&gt;
&lt;li&gt;Helm&lt;&#x2F;li&gt;
&lt;li&gt;Docker&lt;&#x2F;li&gt;
&lt;li&gt;Terraform&lt;&#x2F;li&gt;
&lt;li&gt;GitHub Actions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you’re adventurous, you might even venture into managed Kubernetes services
like EKS or GKE. It’s tempting, with just a few clicks, your application is
ready to roll. But the reality hits when you start juggling monitoring, logging,
security, scaling, and more.&lt;&#x2F;p&gt;
&lt;p&gt;Soon, you find yourself unintentionally leading a DevOps team instead of
focusing on your product. You hire more staff to manage infrastructure while
your competitors are shipping features and growing their user base.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-frustration&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#my-frustration&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;My Frustration&lt;&#x2F;h2&gt;
&lt;p&gt;The cloud promised to make infrastructure easy, but the array of tools and
services can be overwhelming. Even if you don’t use them all, you must be aware
of their existence and learn the basics. The result? Your focus on the product
diminishes.&lt;&#x2F;p&gt;
&lt;p&gt;I appreciate dealing with infrastructure, but I also love delivering a product.
Sadly, many companies waste precious time and money on infrastructure, repeating
the same mistakes.&lt;&#x2F;p&gt;
&lt;p&gt;What if there was a way to eliminate infrastructure concerns altogether?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-allure-of-serverless&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-allure-of-serverless&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Allure of Serverless&lt;&#x2F;h2&gt;
&lt;p&gt;Serverless architecture seems promising - no servers, no containers, just pure
business logic. However, it’s not without challenges:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Cold start times&lt;&#x2F;li&gt;
&lt;li&gt;Lambda size limitations&lt;&#x2F;li&gt;
&lt;li&gt;Memory issues&lt;&#x2F;li&gt;
&lt;li&gt;Long-running processes&lt;&#x2F;li&gt;
&lt;li&gt;Debugging complexities&lt;&#x2F;li&gt;
&lt;li&gt;Lack of local testing&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Serverless has its merits for certain use cases, but for larger applications,
you might still need some servers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;platform-as-a-service-paas&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#platform-as-a-service-paas&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Platform-As-A-Service (PaaS)&lt;&#x2F;h2&gt;
&lt;p&gt;Platforms like Heroku and Netlify introduced a third option – managed services
that handle all infrastructure for you. No more infrastructure concerns; you
simply push code, and it deploys. What’s great about these solutions is their
deep integration with specific programming language ecosystems.&lt;&#x2F;p&gt;
&lt;p&gt;I was looking for a platform tailored for Rust developers, aiming to provide a
top-notch developer experience. I wanted deep integration with the Rust
ecosystem (serde, sqlx, axum,…).&lt;&#x2F;p&gt;
&lt;p&gt;A while ago, I came across &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shuttle.rs&#x2F;&quot;&gt;Shuttle&lt;&#x2F;a&gt; while trying to
find ways to make my Rust
development workflow a bit smoother. It’s a tool that kind of just fits into the
existing Rust ecosystem, letting you use cargo as you normally would, but with
some of the infrastructural heavy lifting taken out of the picture. Now, it’s
not a magic wand that solves all problems, but what I appreciate about Shuttle
is its simplicity. You’re not thrown into a completely new environment with a
steep learning curve. Instead, you stick to your Rust code, and Shuttle is there
in the background, helping manage some of the server-side complexities. So, in
essence, it’s about sticking to what you know, while maybe making life a tad
easier when it comes to deployment and server management. It’s not about a
revolutionary change in how you code, but more about a subtle shift in managing
the background processes that can sometimes be a bit of a headache.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-shuttle-experience-so-far&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#my-shuttle-experience-so-far&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;My Shuttle Experience So Far&lt;&#x2F;h2&gt;
&lt;p&gt;Until now, I built two smaller Rust services with Shuttle: Zerocal and Readable.&lt;&#x2F;p&gt;
&lt;p&gt;Shuttle takes your Rust code and with very few annotations, it can be
deployed to the cloud. The developer experience is pretty close to ideal
given that provisioning and deployment are usually the most painful parts of
building a service.&lt;&#x2F;p&gt;
&lt;p&gt;Instead, it’s just a matter of adding a few lines of code. See for yourself.
The boilerplate just vanishes. What’s left is the business logic.&lt;&#x2F;p&gt;
 &lt;video width=&quot;720&quot; height=&quot;480&quot; autoplay muted loop&gt;
  &lt;source src=&quot;video.mp4&quot; type=&quot;video&#x2F;mp4&quot;&gt;
Your browser does not support the video tag. :( But the video is great.
&lt;&#x2F;video&gt; 
&lt;h3 id=&quot;zerocal-stateless-calendar-magic&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#zerocal-stateless-calendar-magic&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Zerocal - Stateless Calendar Magic&lt;&#x2F;h3&gt;
&lt;p&gt;Zerocal was the first project I deployed on Shuttle.
The principle was very simple yet innovative: encode calendar data directly into a URL. This means creating an event was as straightforward as:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;curl&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; https:&#x2F;&#x2F;zerocal.shuttleapp.rs?start=2023-11-04+20:00&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This would return an iCal file, that you can add to your calendar.
Here’s how you create an event in the browser:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2023&amp;#x2F;move-fast-rust&amp;#x2F;form.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2023&amp;#x2F;move-fast-rust&amp;#x2F;form.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;195&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;I tried building this project on Shuttle when they were still fixing some things and changing their APIs here and there. Even with these small issues, it was a good experience. In just a few minutes, my app was up and running.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the code to start the service including the axum routes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;shuttle_runtime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; shuttle_axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;ShuttleAxum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; just normal axum routes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    		.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;route&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    		.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;route&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; post&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;	Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I don’t really need Zerocal for myself anymore, so I’m hoping someone else might
want to take it over. I think it could be really useful for sharing invites on
places like GitHub or Discord. If you want to know more about Zerocal, you can
read &lt;a href=&quot;&#x2F;2022&#x2F;zerocal&#x2F;&quot;&gt;this detailed breakdown&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I would also like to mention that someone else built a similar project inspired
by Zerocal: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;maheshsundaram&#x2F;kiwi&quot;&gt;kiwi&lt;&#x2F;a&gt; by  &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;maheshsundaram&#x2F;&quot;&gt;Mahesh Sundaram&lt;&#x2F;a&gt;, written in Deno. This is a really cool outcome.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;a-reader-mode-for-my-e-reader&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a-reader-mode-for-my-e-reader&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;A Reader Mode For My E-Reader&lt;&#x2F;h3&gt;
&lt;p&gt;My appreciation for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;support.mozilla.org&#x2F;en-US&#x2F;kb&#x2F;firefox-reader-view-clutter-free-web-pages&quot;&gt;Firefox’s reader view&lt;&#x2F;a&gt; sparked the creation of a &lt;a href=&quot;&#x2F;2022&#x2F;readable&#x2F;&quot;&gt;Reader Mode
Proxy&lt;&#x2F;a&gt; for a minimalist, JavaScript-free web reading experience, particularly
tailored for e-readers. The intention was to transform verbose websites into a
more digestible format for distraction-free reading.&lt;&#x2F;p&gt;
&lt;p&gt;This project deeply reflected my personal preferences, as I like simple
apps that solve a problem. With just a sprinkle of annotations, my code adapted
smoothly to Shuttle’s environment. Initially, I had my own local mode, which
allowed me to run the app on my machine for testing, but I found no need to
maintain that because Shuttle’s own local mode works just as well.&lt;&#x2F;p&gt;
&lt;p&gt;While developing the app, there were some bumps along the road. Service
downtimes required some code revamping. Yet, Shuttle’s evolution simplified
parts of my process, especially when it introduced native static file handling.&lt;&#x2F;p&gt;
&lt;p&gt;Before it looked like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;shuttle_runtime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; shuttle_axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;ShuttleAxum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Previously, I needed to manually serve static files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    	.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;route&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;        	&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;static&#x2F;Crimson.woff2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        	get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; async&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            	static_content&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                	include_bytes!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;static&#x2F;fonts&#x2F;Crimson.woff2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;                	HeaderValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_static&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text&#x2F;woff2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            	)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        	}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    	)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    	.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;route&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;        	&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;static&#x2F;JetBrainsMono.woff2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        	get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; async&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;            	static_content&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                	include_bytes!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;static&#x2F;fonts&#x2F;JetBrainsMono.woff2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;                	HeaderValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_static&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;font&#x2F;woff2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            	)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        	}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    	)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    	.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fallback&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;readable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;	Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now it’s just&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;shuttle_runtime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; shuttle_axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;ShuttleAxum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;   let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    	.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;nest_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; ServeDir&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    	.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;fallback&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;readable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;	Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To understand the intricacies of this project, &lt;a href=&quot;&#x2F;2022&#x2F;readable&quot;&gt;here’s a more comprehensive
look&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;control-and-safety&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#control-and-safety&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Control and Safety&lt;&#x2F;h2&gt;
&lt;p&gt;Initially, I was concerned that annotating my code for infrastructure would
cause vendor lock-in. I wanted to retain full control over my project. Want to
move away? The Shuttle macros get rid of the boilerplate, so I could just remove
the 2 annotations I’ve added and get the original code back. Shuttle’s code is
also open source, so I could even set up your self-hosted instance —
although I wouldn’t want to.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-true-cost-of-diy-infrastructure&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-true-cost-of-diy-infrastructure&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The True Cost of DIY Infrastructure&lt;&#x2F;h2&gt;
&lt;p&gt;Infrastructure may seem easy on the surface, but maintaining it involves various
complexities and costs. Updates, deployments, availability – it can be
overwhelming. Each hour spent on these tasks carries both a direct and
opportunity cost.&lt;&#x2F;p&gt;
&lt;p&gt;Infrastructure can be a maze, and Shuttle seems to fit well for those working
with Rust. I’m thinking of trying out a larger project on Shuttle soon, now that
I’ve got a decent understanding of what Shuttle can and can’t do. If you’re
considering giving it a shot, it’s wise to check their
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shuttle.rs&#x2F;pricing&quot;&gt;pricing&lt;&#x2F;a&gt; to ensure it aligns with your needs.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Be mindful of the real cost of infrastructure!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;As I’ve mentioned before, it’s
not just server costs, but a lot more. The biggest factor will probably be human
labor for maintenance and debugging infrastructure and that is expensive. If I
were to use infrastructure as code, I’d be spending many hours setting up my
infrastructure and a lot more to maintain it and that can be expensive, given
today’s salaries.&lt;&#x2F;p&gt;
&lt;p&gt;Even if it was just for a hobby project, it would not be worth
the trouble for me. I’d much rather work on features than the code that runs it
all.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Little Helpers</title>
        <published>2023-01-05T00:00:00+00:00</published>
        <updated>2023-01-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2023/helpers/"/>
        <id>https://endler.dev/2023/helpers/</id>
        
        <content type="html" xml:base="https://endler.dev/2023/helpers/">&lt;p&gt;Yesterday I couldn’t help but feel a sense of awe at all the conveniences modern
life has to offer.&lt;&#x2F;p&gt;
&lt;p&gt;A lot of the chores in our household are taken care of by little helpers: The
dishwasher washes the dishes, the washing machine washes the clothes, and the
robot vacuum cleaner cleans the floors. The refrigerator keeps our food cold,
the microwave heats it up, and the oven cooks it.&lt;&#x2F;p&gt;
&lt;p&gt;We take all of this for granted because the devices rarely fail, but it’s really
amazing when you think about it. It’s only been a few decades since much of this
was tedious, time-consuming, manual labor.&lt;&#x2F;p&gt;
&lt;p&gt;I heard stories about how people used to watch the washing machine do its thing,
just because it was entertaining to see the machine do their work for them.&lt;&#x2F;p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;BZoKfap4g4w&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;rosling.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;rosling.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;p&gt;Growing up in the 90s and early 2000s, I remember when “smart home” was a
buzzword, and now it’s a reality. Smart devices control the thermostat and soon
the lights and the door locks in our apartment.&lt;&#x2F;p&gt;
&lt;p&gt;Of course there were a bunch of stupid ideas that didn’t work out along the way.
I remember when they tried to sell those “smart” fridges that would run a web
browser and let you order groceries from the fridge. Who would want to do that?
It’s so much easier to just order groceries online from your phone or computer.
On the other hand, of all the people I talked to, I’ve never met anyone who
regrets buying a vacuum robot.&lt;&#x2F;p&gt;
&lt;p&gt;We recently got a cat and quickly automated all the tedious stuff. The litter
box cleans itself, there’s a water fountain that keeps the water fresh, and soon
we’ll get a food dispenser. That means we have more time to focus on the fun
stuff, like playing with the cat.&lt;&#x2F;p&gt;
&lt;p&gt;And yes, I fully realize that this convenience comes from an incredible position of
privilege. A privileged position that we should never take for granted! Instead,
we should be grateful for the little helpers that make our lives easier and make
them more accessible to everyone.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Reader Mode Proxy for the Slow Web</title>
        <published>2022-11-03T00:00:00+00:00</published>
        <updated>2022-11-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2022/readable/"/>
        <id>https://endler.dev/2022/readable/</id>
        
        <content type="html" xml:base="https://endler.dev/2022/readable/">&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;readable.shuttleapp.rs&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;readable&amp;#x2F;darkmode.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;readable&amp;#x2F;darkmode.jpg&quot; 
        
            alt=&quot;Reader showing an article in light and dark mode.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;421&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
        &lt;figcaption&gt;
            
            Reader showing an article in light and dark mode.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;em&gt;tl;dr:&lt;&#x2F;em&gt; I built a service that takes any article and creates a pleasant-to-read, printable version.
It is similar to Reader View in Firefox&#x2F;Safari, but also works on older
browsers, can be shared and has a focus on beautiful typography.
Check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;readable-app&#x2F;readable&quot;&gt;source code&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;The web used to be such a fun place.&lt;&#x2F;p&gt;
&lt;p&gt;Nowadays? Meh.
Trackers, ads, bloat, fullscreen popups, autoplaying videos… it’s all so &lt;em&gt;exhausting&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I just want to read long-form posts without distractions with a good cup of tea,
the cat sleeping on the windowsill and some light snow falling in front of the window.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;readable&amp;#x2F;lofi.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;readable&amp;#x2F;lofi.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;366&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;the-slow-web&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-slow-web&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Slow Web&lt;&#x2F;h2&gt;
&lt;p&gt;I’m a big fan of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.jackcheng.com&#x2F;the-slow-web&#x2F;&quot;&gt;Slow Web movement&lt;&#x2F;a&gt;
and of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;herman.bearblog.dev&#x2F;big-fat-websites&#x2F;&quot;&gt;little sites that do one thing well&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For reading long-form text clutter-free I use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;support.mozilla.org&#x2F;en-US&#x2F;kb&#x2F;firefox-reader-view-clutter-free-web-pages&quot;&gt;Reader
View&lt;&#x2F;a&gt;
in Firefox, and while it doesn’t always work and it’s not the prettiest I like it.&lt;&#x2F;p&gt;
&lt;p&gt;There are reader modes in other browsers as well, but some of them — like Chrome — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.howtogeek.com&#x2F;423643&#x2F;how-to-use-google-chromes-hidden-reader-mode&#x2F;&quot;&gt;hide
it behind a feature flag&lt;&#x2F;a&gt;.
Other browsers, like the one on my eBook reader, don’t come with a reader mode at all,
which leaves me with a subpar and slow browsing experience on my main device used for reading.&lt;&#x2F;p&gt;
&lt;p&gt;So I built &lt;em&gt;a reader mode as a service&lt;&#x2F;em&gt; with a focus on &lt;em&gt;beautiful typography&lt;&#x2F;em&gt;
which works across all browsers.
It’s very basic, but I use it to read articles on my older devices and
it could also make content more accessible in regions with low bandwidth or
while travelling.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-it&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#building-it&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Building It&lt;&#x2F;h2&gt;
&lt;p&gt;Lately I saw a post about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=33192518&quot;&gt;circumflex, a Hacker News terminal
client&lt;&#x2F;a&gt;. The tool did a solid job
at rendering website content and I wondered if I can retrofit that into a proxy
server.&lt;&#x2F;p&gt;
&lt;p&gt;The Golang cleanup code is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;bensadeh&#x2F;circumflex&#x2F;blob&#x2F;d69467963e4a27f1ea75f0017ee4d4decc304de4&#x2F;reader&#x2F;reader.go#L16-L36&quot;&gt;here&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; GetArticle&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; title&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; width&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-numeric z-go&quot;&gt; int&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; indentationSymbol&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-string z-go&quot;&gt; string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-string z-go&quot;&gt;string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-error z-go&quot;&gt; error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    articleInRawHTML&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; httpErr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; readability&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;FromURL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;Second&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; httpErr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; nil&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fmt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Errorf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;could not fetch url: &lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-placeholder&quot;&gt;%w&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; httpErr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;They use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;go-shiori&#x2F;go-readability&quot;&gt;go-readability&lt;&#x2F;a&gt;, a port
of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mozilla&#x2F;readability&quot;&gt;Mozilla’s Readability&lt;&#x2F;a&gt;. The Rust
equivalent is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;readability&quot;&gt;readability&lt;&#x2F;a&gt; and it’s
simple enough to use:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; readability&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;extractor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; extractor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;scrape&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;endler.dev&#x2F;2022&#x2F;readable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Before we write a full proxy server, let’s write a simple CLI tool that takes a
URL and outputs a clean, readable HTML file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; readability&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;extractor&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;File&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; read the URL from the command line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; url&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;nth&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Please provide a URL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; extractor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;scrape&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; File&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;create&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;index.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;content&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;as_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;	Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output already looked surprisingly good.
Next I added a simple HTML template to wrap the response content.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;DOCTYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;en&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;meta&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; charset&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;UTF-8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Document&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;link&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; rel&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;stylesheet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; href&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;yue.css&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;style&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text&#x2F;css&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-entity z-name z-tag z-css&quot;&gt;      body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;        margin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;        padding&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0.4&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;em&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;em&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;em&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;        background&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-other z-color z-rgb-value&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-color z-rgb-value&quot;&gt;fff&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css z-entity z-other z-attribute-name z-class z-css&quot;&gt;      .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name z-class z-css&quot;&gt;yue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;        max-width&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 650&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;        margin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; auto&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;style&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;head&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;yue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;{{content}}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No need to use a full-blown template engine for now; we can just use
&lt;code&gt;str::replace&lt;&#x2F;code&gt; to replace the &lt;code&gt;{{content}}&lt;&#x2F;code&gt; placeholder with the actual content.
😉&lt;&#x2F;p&gt;
&lt;h2 id=&quot;proxy-setup&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#proxy-setup&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Proxy Setup&lt;&#x2F;h2&gt;
&lt;p&gt;The proxy setup is super simple with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shuttle.rs&#x2F;&quot;&gt;shuttle&lt;&#x2F;a&gt;. It’s my
second project after &lt;a href=&quot;&#x2F;2022&#x2F;zerocal&#x2F;&quot;&gt;zerocal&lt;&#x2F;a&gt;, which is hosted on shuttle and
I’m very happy with how smooth the process is. 🚀
Let’s call the app &lt;code&gt;readable&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo shuttle init --axum --name readable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This creates a small &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;axum&quot;&gt;Axum&lt;&#x2F;a&gt; app with a simple
hello world route.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;roadblock-no-1-reqwest&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#roadblock-no-1-reqwest&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Roadblock No. 1: &lt;code&gt;reqwest&lt;&#x2F;code&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When I integrated the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;readability&quot;&gt;readability&lt;&#x2F;a&gt; crate
into the project I hit a minor roadblock.&lt;&#x2F;p&gt;
&lt;p&gt;I used &lt;code&gt;extractor::scrape&lt;&#x2F;code&gt; just like above and the proxy started locally.
However when I wanted to fetch a website from the proxy, I got an error:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;thread &amp;#39;tokio-runtime-worker&amp;#39; panicked at&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;#39;Cannot drop a runtime in a context where blocking is not allowed.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;This happens when a runtime is dropped from&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;within an asynchronous context.&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This meant that I started a runtime inside a runtime.&lt;&#x2F;p&gt;
&lt;p&gt;After checking the source code of the &lt;code&gt;readability&lt;&#x2F;code&gt; crate, I found that it
builds a &lt;code&gt;reqwest::blocking::Client&lt;&#x2F;code&gt; and uses that to fetch the URL.
After that request, the client is dropped which causes the runtime to be shut
down.&lt;&#x2F;p&gt;
&lt;p&gt;I fixed this by using a &lt;code&gt;reqwest::Client&lt;&#x2F;code&gt; instead of the &lt;code&gt;reqwest::blocking::Client&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; reqwest::blocking::Client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; reqwest&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;blocking&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; reqwest::Client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; reqwest&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now I had the content of the article, but I still needed to pass it to
&lt;code&gt;readability&lt;&#x2F;code&gt;. Fortunately they provide a function named &lt;code&gt;extractor::extract&lt;&#x2F;code&gt;
that takes something that implements &lt;code&gt;Read&lt;&#x2F;code&gt; and returns the extracted content.&lt;&#x2F;p&gt;
&lt;p&gt;However, the &lt;code&gt;reqwest::Response&lt;&#x2F;code&gt; doesn’t implement &lt;code&gt;Read&lt;&#x2F;code&gt; (in contrast to the
&lt;code&gt;reqwest::blocking::Response&lt;&#x2F;code&gt;). So I needed to convert it to a &lt;code&gt;Read&lt;&#x2F;code&gt;able type
myself.&lt;&#x2F;p&gt;
&lt;p&gt;Luckily, the &lt;code&gt;reqwest::Response&lt;&#x2F;code&gt; has a &lt;code&gt;bytes&lt;&#x2F;code&gt; method that returns a &lt;code&gt;Bytes&lt;&#x2F;code&gt;
object. The &lt;code&gt;Bytes&lt;&#x2F;code&gt; object implements &lt;code&gt;Read&lt;&#x2F;code&gt; and I can use it to call
&lt;code&gt;extractor::extract&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; body&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;await&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; extractor&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;extract&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;roadblock-no-2-routing&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#roadblock-no-2-routing&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Roadblock No. 2: Routing&lt;&#x2F;h2&gt;
&lt;p&gt;The app didn’t crash anymore, but I still didn’t get any response.&lt;&#x2F;p&gt;
&lt;p&gt;My router looked like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;shuttle_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; shuttle_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;ShuttleAxum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;route&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;:url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;readable&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; sync_wrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; SyncWrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;router&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;sync_wrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Turns out that when I use &lt;code&gt;&#x2F;:url&lt;&#x2F;code&gt; as the route, it doesn’t match the path
&lt;code&gt;&#x2F;https:&#x2F;&#x2F;example.com&lt;&#x2F;code&gt; because &lt;code&gt;:&lt;&#x2F;code&gt; matches only a single segment up to the
first slash.&lt;&#x2F;p&gt;
&lt;p&gt;The solution was to use &lt;code&gt;&#x2F;*url&lt;&#x2F;code&gt; instead, which is a wildcard route that matches
all segments until the end.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;typography-and-layout&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#typography-and-layout&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Typography and Layout&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;readable&amp;#x2F;nyt.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;readable&amp;#x2F;nyt.jpg&quot; 
        
            alt=&quot;New York Times website (left) vs reader mode (right)&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;206&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            New York Times website (left) vs reader mode (right)
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;For my first prototype I used a CSS framework called
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;typlog&#x2F;yue.css&quot;&gt;yue.css&lt;&#x2F;a&gt; because it was the first thing I
found which looked nice.&lt;&#x2F;p&gt;
&lt;p&gt;For the final version I ended up mimicking the style of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ruudvanasseldonk.com&#x2F;&quot;&gt;Ruud van Asseldonk’s
blog&lt;&#x2F;a&gt; because it always reminded me of reading a
well-typeset book.&lt;&#x2F;p&gt;
&lt;p&gt;For fonts I chose two of my favorites&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Fonthausen&#x2F;CrimsonPro&quot;&gt;Crimson Pro&lt;&#x2F;a&gt; for the body text.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.jetbrains.com&#x2F;lp&#x2F;mono&#x2F;&quot;&gt;JetBrains Mono&lt;&#x2F;a&gt; for the code.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Both are licensed under the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;opensource.org&#x2F;license&#x2F;openfont-html&#x2F;&quot;&gt;SIL Open Font License 1.1&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can even use &lt;code&gt;readable&lt;&#x2F;code&gt; from the terminal.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;lynx https:&#x2F;&#x2F;readable.shuttleapp.rs&#x2F;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Alan_Turing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;caveats&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#caveats&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Caveats&lt;&#x2F;h2&gt;
&lt;p&gt;The proxy is far from perfect.
It’s something I built in a few hours for my personal use.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;It doesn’t always produce valid HTML.&lt;&#x2F;li&gt;
&lt;li&gt;JavaScript is not executed, so some websites don’t work properly. Some might
say that’s feature, not a bug. 😉&lt;&#x2F;li&gt;
&lt;li&gt;That is also true for websites with sophisticated paywalls or bot-detection. A
workaround would be to use a headless browser like
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.scrapingbee.com&quot;&gt;ScrapingBee&lt;&#x2F;a&gt; or
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.browserless.io&#x2F;&quot;&gt;Browserless&lt;&#x2F;a&gt;, but I didn’t want to add that
complexity to the project.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;readability&lt;&#x2F;code&gt; library takes a lot of freedom in formatting the document
however it pleases. It can sometimes produce weird results. For example, it
loves to mangle code blocks.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;credits&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#credits&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Credits&lt;&#x2F;h2&gt;
&lt;p&gt;I was not the first person to build a readability proxy. I found out about
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;n1k0&#x2F;readable-proxy&quot;&gt;readable-proxy&lt;&#x2F;a&gt; when I did my research,
but the project seems to be abandoned. Nevertheless it was nice to see that
others had the same need.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ruudvanasseldonk.com&#x2F;&quot;&gt;Ruud van Asseldonk&lt;&#x2F;a&gt; for open sourcing
his &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ruuda&#x2F;blog&quot;&gt;blog&lt;&#x2F;a&gt;. 🙏 His writing and documentation are
always a great source of inspiration to me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#conclusion&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;readable&amp;#x2F;kobo.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;readable&amp;#x2F;kobo.jpg&quot; 
        
            alt=&quot;The browser on my old Kobo eBook reader using the readability proxy.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;436&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            The browser on my old Kobo eBook reader using the readability proxy.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In times where &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tech.co&#x2F;news&#x2F;google-chrome-ad-blockers-2023&quot;&gt;the most popular browser might kill off ad
blockers&lt;&#x2F;a&gt;, a little service
for reading articles without ads or tracking can come in handy. I’m not saying you
should use it to send all your traffic through it, but it’s a nice tool to have
in your toolbox for a rainy day, a warm drink and a great article. ☕&lt;&#x2F;p&gt;
&lt;p&gt;Feel free to deploy your own instance of &lt;code&gt;readable&lt;&#x2F;code&gt; or use the one I’m hosting.
The source code is available on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;readable&quot;&gt;GitHub&lt;&#x2F;a&gt;.
Maybe one of you wants to help me maintain it.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>zerocal - A Serverless Calendar App in Rust Running on shuttle.rs</title>
        <published>2022-10-05T00:00:00+00:00</published>
        <updated>2022-10-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2022/zerocal/"/>
        <id>https://endler.dev/2022/zerocal/</id>
        
        <content type="html" xml:base="https://endler.dev/2022/zerocal/">&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;zerocal&amp;#x2F;intro.svg&quot; 
        

        

        
        
        
            width=&quot;487&quot;
        
        
            height=&quot;264&quot;
         
    &#x2F;&gt;
    

    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;Every once in a while my buddies and I meet for dinner.
I value these evenings, but the worst part is scheduling these events!&lt;&#x2F;p&gt;
&lt;p&gt;We send out a message to the group.&lt;br &#x2F;&gt;
We wait for a response.&lt;br &#x2F;&gt;
We decide on a date.&lt;br &#x2F;&gt;
Someone sends out a calendar invite.&lt;br &#x2F;&gt;
Things finally happen.&lt;&#x2F;p&gt;
&lt;p&gt;None of that is fun &lt;em&gt;except&lt;&#x2F;em&gt; for the dinner.&lt;&#x2F;p&gt;
&lt;p&gt;Being the reasonable person you are, you would think: “Why don’t you just use a
scheduling app?”.&lt;&#x2F;p&gt;
&lt;p&gt;I have tried many of them. None of them are any good.
They are all… &lt;em&gt;too much&lt;&#x2F;em&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;Just let me send out an invite and whoever wants can show up.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I &lt;em&gt;don’t&lt;&#x2F;em&gt; want to have to create an account for your calendar&#x2F;scheduling&#x2F;whatever app.&lt;&#x2F;li&gt;
&lt;li&gt;I &lt;em&gt;don’t&lt;&#x2F;em&gt; want to have to add my friends.&lt;&#x2F;li&gt;
&lt;li&gt;I &lt;em&gt;don’t&lt;&#x2F;em&gt; want to have to add my friends’ friends.&lt;&#x2F;li&gt;
&lt;li&gt;I &lt;em&gt;don’t&lt;&#x2F;em&gt; want to have to add my friends’ friends’ friends.&lt;&#x2F;li&gt;
&lt;li&gt;You get the idea:
I just want to send out an invite and get no response from you.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;the-nerdy-introvert-engineer-s-solution&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-nerdy-introvert-engineer-s-solution&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The nerdy, introvert engineer’s solution&lt;&#x2F;h2&gt;
&lt;p&gt;💡 What we definitely need is yet another calendar app which allows us to create events and send out an invite with a link to that event!
You probably didn’t see that coming now, did you?&lt;&#x2F;p&gt;
&lt;p&gt;Oh, and I don’t want to use Google Calendar to create the event because &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.businessinsider.com&#x2F;google-users-locked-out-after-years-2020-10&quot;&gt;I&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;killedbygoogle.com&#x2F;&quot;&gt;don’t&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tycrek&#x2F;degoogle&quot;&gt;trust them&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Like any reasonable person, I wanted a way to create calendar entries from my &lt;em&gt;terminal&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;That’s how I pitched the idea to my buddies last time.
The answer was: “I don’t know, sounds like a solution in search of a problem.”
But you know what they say: Never ask a starfish for directions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;show-don-t-tell&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#show-don-t-tell&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Show, don’t tell&lt;&#x2F;h2&gt;
&lt;p&gt;That night I went home and built a website that would create a calendar entry
from &lt;code&gt;GET&lt;&#x2F;code&gt; parameters.&lt;&#x2F;p&gt;
&lt;p&gt;It allows you to create a calendar event from the convenience of your command line:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; curl https:&#x2F;&#x2F;zerocal.shuttleapp.rs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;BEGIN:VCALENDAR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;VERSION:2.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;PRODID:ICALENDAR-RS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;CALSCALE:GREGORIAN&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;BEGIN:VEVENT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;DTSTAMP:20221002T123149Z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;CLASS:CONFIDENTIAL&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;DESCRIPTION:paaarty&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;DTEND:20221002T133149Z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;DTSTART:20221002T123149Z&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;SUMMARY:Birthday&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;UID:c99dd4bb-5c35-4d61-9c46-7a471de0e7f4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;END:VEVENT&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;END:VCALENDAR&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can then save that to a file and open it with your calendar app.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; curl https:&#x2F;&#x2F;zerocal.shuttleapp.rs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;p&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; birthday.ics&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; open birthday.ics&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In a sense, it’s a “serverless calendar app”, haha.
There is no state on the server, it just generates a calendar event on the fly and returns it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-i-built-it&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#how-i-built-it&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;How I built it&lt;&#x2F;h2&gt;
&lt;p&gt;You probably noticed that the URL contains “shuttleapp.rs”.
That’s because I’m using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;shuttle-hq&#x2F;shuttle&quot;&gt;shuttle.rs&lt;&#x2F;a&gt; to host the website.&lt;&#x2F;p&gt;
&lt;p&gt;Shuttle is a hosting service for Rust projects and I wanted to try it out for a long time.&lt;&#x2F;p&gt;
&lt;p&gt;To initialize the project using the awesome &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;axum&quot;&gt;axum&lt;&#x2F;a&gt; web framework, I’ve used&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo install cargo-shuttle&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo shuttle init --axum --name zerocal zerocal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and I was greeted with everything I needed to get started:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;routing&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; sync_wrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;SyncWrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; hello_world&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;static&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; str&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;shuttle_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; axum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; shuttle_service&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;ShuttleAxum&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Router&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;route&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;hello_world&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; sync_wrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; SyncWrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;router&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;  Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;sync_wrapper&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s quickly commit the changes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .gitignore&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; Cargo.toml&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; src&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;git&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; commit&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;m&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello World&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To deploy the code, I needed to sign up for a shuttle account.
This can be done over at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shuttle.rs&#x2F;login&quot;&gt;https:&#x2F;&#x2F;www.shuttle.rs&#x2F;login&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It will ask you to authorize it to access your Github account.&lt;&#x2F;p&gt;
&lt;p&gt;Then:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; shuttle&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; login&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and finally:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; shuttle&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; deploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now let’s head over to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zerocal.shuttleapp.rs&quot;&gt;zerocal.shuttleapp.rs&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Hello World!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Deploying the first version took less than 5 minutes. Neat!
We’re all set for our custom calendar app.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;writing-the-app&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#writing-the-app&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Writing the app&lt;&#x2F;h2&gt;
&lt;p&gt;To create the calendar event, I used the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hoodie&#x2F;icalendar-rs&quot;&gt;icalendar&lt;&#x2F;a&gt; crate (shout out to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hoodie&quot;&gt;hoodie&lt;&#x2F;a&gt; for creating this nice library!). &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;ICalendar&quot;&gt;iCalendar&lt;&#x2F;a&gt; is a standard for creating calendar events that is supported by most calendar apps.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; icalendar&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; chrono&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; For date and time parsing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s create a demo calendar event:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;test event&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;here I have something really important to do&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;starts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Utc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ends&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Utc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; Duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;days&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;  .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Simple enough.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-return-a-file&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#how-to-return-a-file&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;How to return a file!?&lt;&#x2F;h2&gt;
&lt;p&gt;Now that we have a calendar event, we need to return it to the user.
But how do we return it as a file?&lt;&#x2F;p&gt;
&lt;p&gt;There’s an example of how to return a file dynamically in axum &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tokio-rs&#x2F;axum&#x2F;discussions&#x2F;608&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; IntoResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; ical&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;      &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; add an event&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;      Event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;It works! 😀&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Meeting with the Rust community&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;starts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Utc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; Duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;hours&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ends&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Utc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; Duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;hours&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  CalendarResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ical&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some interesting things to note here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Every calendar file is a collection of events so we wrap the event in a
&lt;code&gt;Calendar&lt;&#x2F;code&gt; object, which represents the collection.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;impl IntoResponse&lt;&#x2F;code&gt; is a trait that allows us to return any type that implements it.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;CalendarResponse&lt;&#x2F;code&gt; is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rust-unofficial.github.io&#x2F;patterns&#x2F;patterns&#x2F;behavioural&#x2F;newtype.html&quot;&gt;newtype wrapper&lt;&#x2F;a&gt; around &lt;code&gt;Calendar&lt;&#x2F;code&gt; that implements &lt;code&gt;IntoResponse&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is the &lt;code&gt;CalendarResponse&lt;&#x2F;code&gt; implementation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Newtype wrapper around Calendar for `IntoResponse` impl&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;derive&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Debug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; CalendarResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; IntoResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; CalendarResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; into_response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;boxed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Full&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;headers_mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;      header&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;CONTENT_TYPE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;      HeaderValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_static&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text&#x2F;calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    )&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    res&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We just create a new &lt;code&gt;Response&lt;&#x2F;code&gt; object and set the &lt;code&gt;Content-Type&lt;&#x2F;code&gt; header to the correct MIME type for iCalendar files: &lt;code&gt;text&#x2F;calendar&lt;&#x2F;code&gt;.
Then we return the response.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;add-date-parsing&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#add-date-parsing&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Add date parsing&lt;&#x2F;h2&gt;
&lt;p&gt;This part is a bit hacky, so feel free to glance over it.
We need to parse the date and duration from the query string.
I used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;dateparser&quot;&gt;dateparser&lt;&#x2F;a&gt;, because it supports &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;dateparser&#x2F;latest&#x2F;dateparser&#x2F;#accepted-date-formats&quot;&gt;sooo many different date formats&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;params&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;HashMap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; IntoResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;class&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Class&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Confidential&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;DEFAULT_EVENT_TITLE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Powered by zerocal.shuttleapp.rs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; dateparser&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;starts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;      let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; humantime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;parse_duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;      let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; chrono&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_std&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;      event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ends&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; end&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; dateparser&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ends&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;      if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;get&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;is_none&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; humantime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;parse_duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; chrono&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_std&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;starts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;end&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; ical&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;done&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  CalendarResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;ical&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Would be nice to support more date formats like &lt;code&gt;now&lt;&#x2F;code&gt; and &lt;code&gt;tomorrow&lt;&#x2F;code&gt;, but I’ll leave that for another time.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s test it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; cargo shuttle run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; This starts a local dev server&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; curl 127.0.0.1:8000&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;4&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;duration&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;B&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;P&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;t&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;🤖 bleep bloop, calendar file created&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Nice, it works!&lt;&#x2F;p&gt;
&lt;p&gt;Opening it in the browser creates a new event in the calendar:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;zerocal&amp;#x2F;event.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;zerocal&amp;#x2F;event.jpg&quot; 
        
            alt=&quot;Of course, it also works on Chrome, but you do [support the open web](https:&amp;#x2F;&amp;#x2F;contrachrome.com&amp;#x2F;), right?&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;193&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Of course, it also works on Chrome, but you do &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;contrachrome.com&#x2F;&quot;&gt;support the open web&lt;&#x2F;a&gt;, right?
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;And for all the odd people who don’t use a terminal to create a calendar event, let’s also add a form to the website.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;add-a-form&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#add-a-form&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Add a form&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;form&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;table&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Event Title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Birthday&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;desc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;desc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;desc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Party&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;datetime-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;start&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;End&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;label&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;input&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;datetime-local&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;end&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;td&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;tr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;table&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;form&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I modified the &lt;code&gt;calendar&lt;&#x2F;code&gt; function a bit to return the form if the query string is empty:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;async&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; calendar&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;params&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Query&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;HashMap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; IntoResponse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; if query is empty, show form&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;is_empty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Response&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;builder&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;      .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;200&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;      .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;boxed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Full&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;include_str!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;..&#x2F;static&#x2F;index.html&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;      .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After some more tweaking, we got ourselves a nice little form in all of its web 1.0 glory:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;zerocal&amp;#x2F;form.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2022&amp;#x2F;zerocal&amp;#x2F;form.jpg&quot; 
        
            alt=&quot;The form&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;195&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            The form
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;And that’s it! We now have a little web app that can create calendar events.
Well, almost. We still need to deploy it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deploying&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#deploying&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Deploying&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo shuttle deploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Right, that’s all. It’s that easy.
Thanks to the folks over at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;shuttle-hq&#x2F;shuttle&quot;&gt;shuttle.rs&lt;&#x2F;a&gt; for making this possible.&lt;&#x2F;p&gt;
&lt;p&gt;The calendar app is now available at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zerocal.shuttleapp.rs&quot;&gt;zerocal.shuttleapp.rs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now I can finally send my friends a link to a calendar event for our next pub crawl.
They’ll surely appreciate it.&lt;sup&gt;yeah&lt;sup&gt;yeah&lt;&#x2F;sup&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;from-zero-to-calendar-in-100-lines-of-rust&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#from-zero-to-calendar-in-100-lines-of-rust&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;From zero to calendar in 100 lines of Rust&lt;&#x2F;h2&gt;
&lt;p&gt;Boy it feels good to be writing some plain HTML again.&lt;br &#x2F;&gt;
Building little apps never gets old.&lt;&#x2F;p&gt;
&lt;p&gt;Check out the source code on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;zerocal&quot;&gt;GitHub&lt;&#x2F;a&gt; and help me make it better! 🙏&lt;&#x2F;p&gt;
&lt;p&gt;Here are some ideas:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;✅ Add location support (e.g. &lt;code&gt;location=Berlin&lt;&#x2F;code&gt; or &lt;code&gt;location=https:&#x2F;&#x2F;zoom.us&#x2F;test&lt;&#x2F;code&gt;).
Thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sigaloid&quot;&gt;sigaloid&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Add support for more human-readable date formats (e.g. &lt;code&gt;now&lt;&#x2F;code&gt;, &lt;code&gt;tomorrow&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Add support for recurring events.&lt;&#x2F;li&gt;
&lt;li&gt;Add support for timezones.&lt;&#x2F;li&gt;
&lt;li&gt;Add Google calendar short-links (&lt;code&gt;https:&#x2F;&#x2F;calendar.google.com&#x2F;calendar&#x2F;render?action=TEMPLATE&amp;amp;dates=20221003T224500Z%2F20221003T224500Z&amp;amp;details=&amp;amp;location=&amp;amp;text=&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;Add example bash command to create a calendar event from the command line.&lt;&#x2F;li&gt;
&lt;li&gt;Shorten the URL (e.g. &lt;code&gt;zerocal.shuttleapp.rs&#x2F;2022-11-04T20:00&#x2F;3h&#x2F;Birthday&#x2F;Party&lt;&#x2F;code&gt;)?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Check out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;zerocal&quot;&gt;issue tracker&lt;&#x2F;a&gt; and feel free to open a PR!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Uber of Poland</title>
        <published>2021-06-14T00:00:00+00:00</published>
        <updated>2021-06-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2021/uber-of-poland/"/>
        <id>https://endler.dev/2021/uber-of-poland/</id>
        
        <content type="html" xml:base="https://endler.dev/2021/uber-of-poland/">&lt;p&gt;A few years ago I visited a friend in Gdańsk, Poland. As we explored the
city, one thing I noticed was that cabs were relatively expensive and there was
no Uber. Instead, most (young) people used a community-organized service called
&lt;em&gt;Night Riders&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I couldn’t find anything about that service on the web, so I decided to write
about it to preserve its history.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;delightfully-low-tech&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#delightfully-low-tech&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Delightfully Low-Tech&lt;&#x2F;h2&gt;
&lt;p&gt;What fascinated me about &lt;em&gt;Night Riders&lt;&#x2F;em&gt; was the way the service operated —
completely via WhatsApp: you post a message in a group chat and one of the free
riders would reply with a 👍 emoji. With that, your ride was scheduled.
You’d pay through PayPal or cash.&lt;&#x2F;p&gt;
&lt;p&gt;In these days of venture-backed startups that need millions in capital before
they turn a profit, this approach is decidedly antagonistic. Basically,
&lt;em&gt;Night Riders&lt;&#x2F;em&gt; built on top of existing infrastructure instead of maintaining their
own ride-hailing platform, sign-up process, or even website.&lt;&#x2F;p&gt;
&lt;p&gt;The service would grow solely by word of mouth. Using existing infrastructure
meant that it was extremely cheap to run and there were almost zero upfront costs without
&lt;a href=&quot;&#x2F;2021&#x2F;first-business&#x2F;&quot;&gt;a single line of code to write&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It simply solved the customer’s problem in the most straightforward way
possible. Of course, there are legal issues regarding data protection, labor
law or payment processing, but the important bit is that they had paying
customers from day one.
The rest is easier to solve than a lack of product market fit.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;in-defense-of-clones&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#in-defense-of-clones&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;In Defense of Clones&lt;&#x2F;h2&gt;
&lt;p&gt;Uber and Lyft can’t be everywhere from the start. While they expand their
businesses, others have the ability to outpace them. There’s an Uber clone in
China (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;didichuxing.com&quot;&gt;DiDi&lt;&#x2F;a&gt;), one in Africa and the Middle East
(&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.careem.com&quot;&gt;Careem&lt;&#x2F;a&gt;) and basically one for every
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20230211164448&#x2F;https:&#x2F;&#x2F;www.gett.com&#x2F;il&#x2F;&quot;&gt;country&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cnbc.com&#x2F;2019&#x2F;04&#x2F;11&#x2F;uber-s-1-risk-factors-competitors-deleteuber-campaign-reputation.html&quot;&gt;in&lt;&#x2F;a&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;taxi.yandex.ru&#x2F;&quot;&gt;the&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gojek.com&#x2F;&quot;&gt;world&lt;&#x2F;a&gt;. The tech
industry rarely talks about these &lt;em&gt;Ubers of X&lt;&#x2F;em&gt;, but they serve millions of
customers. While they start as exact copies of their well-known counterparts,
some of them end up offering better service thanks to their understanding of the
local market.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;people-always-find-a-way&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#people-always-find-a-way&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;People always find a way&lt;&#x2F;h2&gt;
&lt;p&gt;With creativity, you can provide great service even without a big budget. The
important part is to know which corners you can cut while staying true to your
mission. If there’s a market, there’s a way. The Cubans have a word for it:
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@d.yau&#x2F;cubas-resolver-mentality-makes-it-the-next-startup-hub-2f10ea2096a0&quot;&gt;&lt;em&gt;resolver&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;,
which means “we’ll figure it out”.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>How Does The Unix `history` Command Work?</title>
        <published>2021-05-31T00:00:00+00:00</published>
        <updated>2021-05-31T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2021/history/"/>
        <id>https://endler.dev/2021/history/</id>
        
        <content type="html" xml:base="https://endler.dev/2021/history/">&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;history&amp;#x2F;hero.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;history&amp;#x2F;hero.jpg&quot; 
        
            alt=&quot;Cozy attic created by [vectorpouch](https:&amp;#x2F;&amp;#x2F;www.freepik.com&amp;#x2F;vectors&amp;#x2F;poster) and tux created by [catalyststuff](https:&amp;#x2F;&amp;#x2F;www.freepik.com&amp;#x2F;vectors&amp;#x2F;baby) &amp;amp;mdash; freepik.com&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;436&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: Cozy attic created by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freepik.com&#x2F;vectors&#x2F;poster&quot;&gt;vectorpouch&lt;&#x2F;a&gt; and tux created by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freepik.com&#x2F;vectors&#x2F;baby&quot;&gt;catalyststuff&lt;&#x2F;a&gt; — freepik.com
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;As the day is winding down, I have a good hour just to myself.
Perfect time to listen to some &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=cJtL8vWNZ4o&quot;&gt;Billie Joel&lt;&#x2F;a&gt; (it’s either Billie Joel or Billie Eilish for me these days) and learn how the Unix &lt;code&gt;history&lt;&#x2F;code&gt; command works.
Life is good.&lt;&#x2F;p&gt;
&lt;p&gt;Learning what makes Unix tick is a bit of a hobby of mine.&lt;br &#x2F;&gt;
I covered &lt;a href=&quot;&#x2F;2017&#x2F;yes&#x2F;&quot;&gt;yes&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;2018&#x2F;ls&#x2F;&quot;&gt;ls&lt;&#x2F;a&gt;, and &lt;a href=&quot;&#x2F;2018&#x2F;fastcat&#x2F;&quot;&gt;cat&lt;&#x2F;a&gt; before.
Don’t judge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-does-history-even-work&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#how-does-history-even-work&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;How does history even work?&lt;&#x2F;h2&gt;
&lt;p&gt;Every command is tracked, so I see the last few commands on my machine when I run &lt;code&gt;history&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;8680&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; endler.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;8682&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; content&#x2F;2021&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;8683&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;8684&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;8685&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; index.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;yeah-but-how-does-it-do-that&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#yeah-but-how-does-it-do-that&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Yeah, but how does it &lt;em&gt;do&lt;&#x2F;em&gt; that?&lt;&#x2F;h2&gt;
&lt;p&gt;The manpage on my mac is not really helpful — I also couldn’t find much in the first place.&lt;&#x2F;p&gt;
&lt;p&gt;I found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;macoclock&#x2F;forced-to-use-zsh-by-macos-catalina-lets-fix-our-history-command-first-9ce86dca540e&quot;&gt;this&lt;&#x2F;a&gt; article (it’s good etiquette nowadays to warn you that this is a Medium link) and it describes a bit of what’s going on.&lt;&#x2F;p&gt;
&lt;p&gt;Every command is stored in &lt;code&gt;$HISTFILE&lt;&#x2F;code&gt;, which points to &lt;code&gt;~&#x2F;.zsh_history&lt;&#x2F;code&gt; for me.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; tail&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;HISTFILE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1586007759:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; endler.dev&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1586007763:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; content&#x2F;2021&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1586007771:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;mkdir&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1586007772:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1586007777:0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; index.md&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So let’s see. We got a &lt;code&gt;:&lt;&#x2F;code&gt; followed by a timestamp followed by &lt;code&gt;:0&lt;&#x2F;code&gt;, then a
separator (&lt;code&gt;;&lt;&#x2F;code&gt;) and finally the command itself. Each new command gets appended
to the end of the file. Not too hard to recreate.&lt;&#x2F;p&gt;
&lt;p&gt;Hold on, what’s that 0 about!?&lt;&#x2F;p&gt;
&lt;p&gt;It turns out it’s the &lt;strong&gt;command duration&lt;&#x2F;strong&gt;, and the entire thing is called the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zsh.sourceforge.io&#x2F;Doc&#x2F;Release&#x2F;Options.html#History&quot;&gt;extended history format&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;beginning&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; tim&lt;&#x2F;span&gt;&lt;span&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;elapsed&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; second&lt;&#x2F;span&gt;&lt;span&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span&gt;command&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Depending on your settings, your file might look different.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hooking-into-history&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#hooking-into-history&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Hooking into history&lt;&#x2F;h2&gt;
&lt;p&gt;But still, how does &lt;code&gt;history&lt;&#x2F;code&gt; &lt;em&gt;really&lt;&#x2F;em&gt; work.&lt;&#x2F;p&gt;
&lt;p&gt;It must run some code whenever I execute a command
— &lt;strong&gt;a hook of some sort&lt;&#x2F;strong&gt;!&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;💥 &lt;strong&gt;Swoooooosh&lt;&#x2F;strong&gt; 💥&lt;&#x2F;p&gt;
&lt;p&gt;Matthias from the future steps out of a blinding ball of light: &lt;em&gt;Waaait!
That’s not really how it works!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;It turns out that shells like bash and zsh don’t &lt;em&gt;actually&lt;&#x2F;em&gt; call a hook for &lt;code&gt;history&lt;&#x2F;code&gt;.
Why should they? When &lt;code&gt;history&lt;&#x2F;code&gt; is a shell builtin, they can just track the commands
&lt;em&gt;internally&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Thankfully my editor-in-chief and resident Unix neckbeard &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m3t0r&quot;&gt;Simon Brüggen&lt;&#x2F;a&gt;
explained that to me — but only &lt;em&gt;after&lt;&#x2F;em&gt; I sent him the first draft for this article. 😓&lt;&#x2F;p&gt;
&lt;p&gt;As such, the next section is a bit like &lt;em&gt;Lord of the Rings&lt;&#x2F;em&gt;: a sympathetic
but naive fellow on a questionable mission with no clue of what he’s getting
himself into.&lt;&#x2F;p&gt;
&lt;p&gt;In my defense, Lord of the Rings is also enjoyed primarily for its entertainment
value, not its &lt;em&gt;historical&lt;&#x2F;em&gt; accuracy…. and just like in this epic story, I
promise we’ll get to the bottom of things in the end.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;I found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zsh.sourceforge.io&#x2F;Doc&#x2F;Release&#x2F;User-Contributions.html&quot;&gt;add-zsh-hook&lt;&#x2F;a&gt;
and a usage example in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ellie&#x2F;atuin&#x2F;blob&#x2F;main&#x2F;atuin&#x2F;src&#x2F;shell&#x2F;atuin.zsh&quot;&gt;atuin’s source code&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I might not fully comprehend all of that is written there, but I’m a man of action, and I can take a solid piece of work and tear it apart.&lt;&#x2F;p&gt;
&lt;p&gt;It’s not much, but here’s what I got:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Source this in your ~&#x2F;.zshrc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;autoload&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add-zsh-hook&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;_past_preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;_past_precmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;precmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;add-zsh-hook&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; _past_preexec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;add-zsh-hook&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; precmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; _past_precmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This sets up two hooks: the first one gets called right before a command gets
executed and the second one directly after. (I decided to call my little
&lt;code&gt;history&lt;&#x2F;code&gt; replacement &lt;em&gt;past&lt;&#x2F;em&gt;. I like short names.)&lt;&#x2F;p&gt;
&lt;p&gt;Okay, let’s tell zsh to totally run this file whenever we execute a command:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;source&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; src&#x2F;shell&#x2F;past.zsh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;…aaaaaand&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;preexec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fri&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; May&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 28&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 18:53:55&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; CEST&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2021&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;precmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It works! ✨ &lt;strong&gt;How exciting!&lt;&#x2F;strong&gt; ✨&lt;&#x2F;p&gt;
&lt;p&gt;Actually, I just remember now that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;envy&#x2F;blob&#x2F;master&#x2F;src&#x2F;hooks&#x2F;zsh.rs&quot;&gt;I did the same thing&lt;&#x2F;a&gt; for my little environment settings manager &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;envy&quot;&gt;envy&lt;&#x2F;a&gt; over two years ago, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wiktionary.org&#x2F;wiki&#x2F;but_hey&quot;&gt;but hey&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
&lt;p&gt;So what to do with our newly acquired power?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-s-run-some-rust-code&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#let-s-run-some-rust-code&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Let’s Run Some Rust Code&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s the thing: only &lt;code&gt;preexec&lt;&#x2F;code&gt; gets the “real” command. &lt;code&gt;precmd&lt;&#x2F;code&gt; gets nothing:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;_past_preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;preexec &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;_past_precmd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    echo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;precmd &lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;$@&lt;&#x2F;code&gt; means “show me what you got” and here’s what it got:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; date&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; date&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Fri&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; May&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 28&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 19:02:11&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; CEST&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2021&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;precmd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;dating&#x2F;comments&#x2F;cbomd5&#x2F;guy_asked_me_to_marry_him_after_first_date&#x2F;&quot;&gt;Shouldn’t one “date” be enough?&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
Hum… let’s look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zsh.sourceforge.io&#x2F;Doc&#x2F;Release&#x2F;Functions.html&quot;&gt;zsh documentation for &lt;code&gt;preexec&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;If the history mechanism is active […], the string that the user typed is passed as the first argument, otherwise it is an empty string. The actual command that will be executed (including expanded aliases) is passed in two different forms: the second argument is a single-line, size-limited version of the command (with things like function bodies elided); the third argument contains the full text that is being executed.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I don’t know about you, but the third argument should be all we ever need? 🤨&lt;&#x2F;p&gt;
&lt;p&gt;Checking…&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ls&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ls&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; lsd&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;l&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; lsd&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Shout out to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Peltoche&#x2F;lsd&quot;&gt;lsd&lt;&#x2F;a&gt;, the next-gen ls command )&lt;&#x2F;p&gt;
&lt;p&gt;Alright, good enough. Let’s parse &lt;code&gt;$3&lt;&#x2F;code&gt; with some Rust code and write it to our own history file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;OpenOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; HISTORY_FILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; history&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; OpenOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;create&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;append&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;open&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;HISTORY_FILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;command&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;nth&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        writeln!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;history&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; command&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dummy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dummy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; hello&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;-&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dummy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; dummy&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; world&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; lol&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;hello&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;world&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We’re almost done — at least if we’re willing to cheat a bit. 😏
Let’s hardcode that format string:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;OpenOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;SystemTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; HISTORY_FILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; timestamp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; SystemTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;duration_since&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;SystemTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;UNIX_EPOCH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;as_secs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;dyn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; history&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; OpenOptions&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;create&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;append&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;true&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;open&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;HISTORY_FILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Some&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;command&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;nth&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        writeln!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;history&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;: &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:0;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; timestamp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; command&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, if we squint a little, it sorta kinda writes our command in my history format.
(That part about the Unix timestamp was taken &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;time&#x2F;struct.SystemTime.html&quot;&gt;straight from the docs&lt;&#x2F;a&gt;. Zero regrets.)&lt;&#x2F;p&gt;
&lt;p&gt;Remember when I said that &lt;code&gt;precmd&lt;&#x2F;code&gt; gets nothing?&lt;&#x2F;p&gt;
&lt;p&gt;I lied.&lt;&#x2F;p&gt;
&lt;p&gt;In reality, you can read the exit code of the executed command (from &lt;code&gt;$?&lt;&#x2F;code&gt;). That’s very helpful, but we just agree to ignore that and never talk about it again.&lt;&#x2F;p&gt;
&lt;p&gt;With this out of the way, our final &lt;code&gt;past.zsh&lt;&#x2F;code&gt; hooks file looks like that:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;autoload&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;U&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; add-zsh-hook&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;_past_preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    past&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; $&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;@&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;add-zsh-hook&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; _past_preexec&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now here comes the dangerous part!
Step back while I replace the original &lt;code&gt;history&lt;&#x2F;code&gt; command with my own.
Never try this at home.
(Actually I’m exaggerating a bit. Feel free to try it. Worst thing that will happen is that you’ll lose a bit of history, but don’t sue me.)&lt;&#x2F;p&gt;
&lt;p&gt;First, let’s change the path to the history file to my real one:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; You should read the ${HISTFILE} env var instead ;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; HISTORY_FILE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;Users&#x2F;mendler&#x2F;.zhistory&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then let’s install &lt;code&gt;past&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; cargo&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; install&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;-path&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; bleep bloop...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After that, it’s ready to use.
Let’s add that bad boy to my &lt;code&gt;~&#x2F;.zshrc&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;source&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;Users&#x2F;mendler&#x2F;Code&#x2F;private&#x2F;past&#x2F;src&#x2F;shell&#x2F;past.zsh&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And FINALLY we can test it.&lt;&#x2F;p&gt;
&lt;p&gt;We open a new shell and run a few commands followed by &lt;code&gt;history&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; it&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; works&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;❯❯❯&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; history&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; 1011&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  date&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; 1012&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  ls&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; 1013&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;  it&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; works&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;✨ &lt;strong&gt;Yay.&lt;&#x2F;strong&gt; ✨ &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;past&quot;&gt;The source code for &lt;code&gt;past&lt;&#x2F;code&gt; is on Github.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-it-really-really-works&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#how-it-really-really-works&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;How it &lt;em&gt;really&lt;&#x2F;em&gt; &lt;em&gt;really&lt;&#x2F;em&gt; works&lt;&#x2F;h2&gt;
&lt;p&gt;Our experiment was a great success, but I since learned that reality is a bit different.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;History_(command)#History&quot;&gt;“In early versions
of Unix the history command was a separate program”&lt;&#x2F;a&gt;, but most modern shells have &lt;code&gt;history&lt;&#x2F;code&gt; builtin.&lt;&#x2F;p&gt;
&lt;p&gt;zsh tracks the history in its main &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zsh-users&#x2F;zsh&#x2F;blob&#x2F;00d20ed15e18f5af682f0daec140d6b8383c479a&#x2F;Src&#x2F;init.c#L120&quot;&gt;run loop&lt;&#x2F;a&gt;.
Here are the important bits. (Assume all types are in scope.)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Eprog prog&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Main zsh run loop &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Init history &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    hbegin&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;prog &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; parse_event&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;ENDINPUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Couldn&amp;#39;t parse command. Stop history &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        hend&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;        continue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Store command in history &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;hend&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;prog&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        LinkList args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        args &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; newlinklist&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        addlinknode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; hist_ring&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;node&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;nam&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        addlinknode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; dupstring&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;getjobtext&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;prog&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        addlinknode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; cmdstr &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; getpermtext&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;prog&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Here&amp;#39;s the preexec hook that we used.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-comment&quot;&gt;        * It gets passed all the args we saw earlier.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        *&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        callhookfunc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;preexec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Main routine for executing a command &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        execode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;prog&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The history lines are kept in a hash, and also in a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Circular_buffer&quot;&gt;ring-buffer&lt;&#x2F;a&gt;
to prevent the history from getting too big. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zsh-users&#x2F;zsh&#x2F;blob&#x2F;00d20ed15e18f5af682f0daec140d6b8383c479a&#x2F;Src&#x2F;hist.c#L98-L103&quot;&gt;See here&lt;&#x2F;a&gt;.)&lt;&#x2F;p&gt;
&lt;p&gt;That’s smart! Without the ring-buffer, a malicious user could just thrash the history with random commands
until a buffer overflow is triggered. I never thought of that.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;history-time-see-what-i-did-there&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#history-time-see-what-i-did-there&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;History time (see what I did there?)&lt;&#x2F;h2&gt;
&lt;p&gt;The original &lt;code&gt;history&lt;&#x2F;code&gt; command was added to the Unix C shell (csh) in 1978.
Here’s a link to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20220605000427&#x2F;http:&#x2F;&#x2F;www.kitebird.com&#x2F;csh-tcsh-book&#x2F;csh-intro.pdf&quot;&gt;the paper&lt;&#x2F;a&gt; by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Bill_Joy&quot;&gt;Bill Joy&lt;&#x2F;a&gt; (hey, another Bill!).
He took inspiration from the &lt;code&gt;REDO&lt;&#x2F;code&gt; command in Interlisp.
You can find its specification in the original Interlisp manual in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;larrymasinter.net&#x2F;86-interlisp-manual-opt.pdf&quot;&gt;section 8.7&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lessons-learned&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#lessons-learned&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Lessons learned&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Rebuild what you don’t understand.&lt;&#x2F;li&gt;
&lt;li&gt;The history file is human-readable and pretty straightforward.&lt;&#x2F;li&gt;
&lt;li&gt;The &lt;code&gt;history&lt;&#x2F;code&gt; command is a shell builtin, but we can use hooks to write our own.&lt;&#x2F;li&gt;
&lt;li&gt;Fun fact: Did you know that in zsh, &lt;code&gt;history&lt;&#x2F;code&gt; is actually just an alias for &lt;code&gt;fc -l&lt;&#x2F;code&gt;? &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zsh.sourceforge.io&#x2F;Doc&#x2F;Release&#x2F;Shell-Builtin-Commands.html&quot;&gt;More info here&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zsh-users&#x2F;zsh&#x2F;blob&#x2F;00d20ed15e18f5af682f0daec140d6b8383c479a&#x2F;Src&#x2F;builtin.c#L86&quot;&gt;check out the source code&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;“What I cannot create, I do not understand” — Richard Feynman&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Spreadsheets Make For Great Business Ideas</title>
        <published>2021-03-10T00:00:00+00:00</published>
        <updated>2025-04-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2021/first-business/"/>
        <id>https://endler.dev/2021/first-business/</id>
        
        <content type="html" xml:base="https://endler.dev/2021/first-business/">&lt;p&gt;One of the best decisions I made in 2020 was to open &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calendly.com&#x2F;matthias-endler&#x2F;chat&quot;&gt;my calendar&lt;&#x2F;a&gt; to everyone. People book appointments to chat about open-source projects, content creation, and business ideas.&lt;&#x2F;p&gt;
&lt;p&gt;When we discuss business ideas, the conversation often leans towards problems suited for startups, such as using artificial intelligence to find clothes that fit or building a crowdfunding platform on the blockchain.&lt;&#x2F;p&gt;
&lt;p&gt;While these are exciting ideas, they require significant persistence and deep pockets. It might be easier and less risky to join an existing startup in that domain.&lt;&#x2F;p&gt;
&lt;p&gt;In reality, most people are simply looking for something cool to work on and to make their customers happy. It turns out you don’t need to run a startup to achieve that (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;every.to&#x2F;napkin-math&#x2F;you-probably-shouldn-t-work-at-a-startup-9387b632-345c-4a22-bac0-3cb92f0eecf1&quot;&gt;and you probably shouldn’t&lt;&#x2F;a&gt;). Instead, starting a side project is less risky and can organically grow into a business over time.&lt;&#x2F;p&gt;
&lt;p&gt;Often, the solution is right in front of them: hidden within an Excel spreadsheet on their computer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-hate-excel&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#i-hate-excel&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;I Hate Excel&lt;&#x2F;h2&gt;
&lt;p&gt;I spend as little time in Excel as possible, only engaging with it when absolutely necessary. My focus is on getting tasks done quickly, not on layout or design; I’d rather pay someone to do that work for me. And this is precisely my point!&lt;&#x2F;p&gt;
&lt;p&gt;The spreadsheets and lists you create to solve your own problems can also solve someone else’s. This represents a business opportunity!&lt;&#x2F;p&gt;
&lt;p&gt;This approach has several advantages:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;💪 It solves a real problem.&lt;&#x2F;li&gt;
&lt;li&gt;🥱 It’s mundane, so people might pay to avoid doing it themselves.&lt;&#x2F;li&gt;
&lt;li&gt;⚡️ It wastes no time on design or infrastructure, embodying the ultimate MVP.&lt;&#x2F;li&gt;
&lt;li&gt;🐢 It’s low-tech: no programming required. You can start with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;notion.so&quot;&gt;Notion&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;super.so&quot;&gt;Super.so&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;🐜 It targets a niche market: if there were an established service, you’d already be using it. Big corporations won’t compete with you.&lt;&#x2F;li&gt;
&lt;li&gt;🚀 It allows you to spend less time building and more time engaging with potential customers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;examples&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#examples&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Examples&lt;&#x2F;h2&gt;
&lt;p&gt;A few years ago, while researching static code analysis tools, I compiled a list, pushed it to GitHub, and moved on. Fast forward, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;analysis-tools.dev&#x2F;&quot;&gt;that side project&lt;&#x2F;a&gt; now generates revenue from sponsors and consulting gigs.&lt;&#x2F;p&gt;
&lt;p&gt;Another example is a person who created a spreadsheet for remote work locations, shared it on Twitter, and then developed a website from it. The website is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nomadlist.com&#x2F;&quot;&gt;NomadList&lt;&#x2F;a&gt;, and its creator, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;levels.io&#x2F;&quot;&gt;Pieter Levels&lt;&#x2F;a&gt;, now earns $300k&#x2F;year.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Instead of building a site first, I simply made [a] public Google spreadsheet to collect the first data and see if there’d be interest for this at all.” — Pieter Levels on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;levels.io&#x2F;product-hunt-hacker-news-number-one&#x2F;&quot;&gt;how he created NomadList&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;strong&gt;I’ve left a spot for your story here.&lt;&#x2F;strong&gt; Now, refine that spreadsheet (or list), share it with your friends, iterate based on their feedback, and build your first business.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Starting A Print-On-Demand Business As A Software Engineer</title>
        <published>2021-01-22T00:00:00+00:00</published>
        <updated>2021-01-22T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2021/codeprints/"/>
        <id>https://endler.dev/2021/codeprints/</id>
        
        <content type="html" xml:base="https://endler.dev/2021/codeprints/">&lt;p&gt;One day I had the idea to make a print of my Github timeline.
I liked the thought of bringing something “virtual” into the real world. 😄&lt;&#x2F;p&gt;
&lt;p&gt;So I called up my friend &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;schafele&quot;&gt;Wolfgang&lt;&#x2F;a&gt; and we built &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codeprints.dev&quot;&gt;codeprints&lt;&#x2F;a&gt;.
It’s my first “physical” product, so I decided to share my learnings.&lt;&#x2F;p&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;twitter.com&amp;#x2F;KrauseFx&amp;#x2F;status&amp;#x2F;1348546742644580353&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;tweet_felix.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;tweet_felix.jpg&quot; 
        
            alt=&quot;[Felix Krause](https:&amp;#x2F;&amp;#x2F;krausefx.com&amp;#x2F;) of [fastlane](https:&amp;#x2F;&amp;#x2F;fastlane.tools&amp;#x2F;) fame was one
of our first customers and we are very thankful for this tweet promoting our
service, which gave us a huge traffic boost.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;860&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
        &lt;figcaption&gt;
            
            &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;krausefx.com&#x2F;&quot;&gt;Felix Krause&lt;&#x2F;a&gt; of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;fastlane.tools&#x2F;&quot;&gt;fastlane&lt;&#x2F;a&gt; fame was one
of our first customers and we are very thankful for this tweet promoting our
service, which gave us a huge traffic boost.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;launching-is-hard-so-launch-early&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#launching-is-hard-so-launch-early&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Launching Is Hard, So Launch Early&lt;&#x2F;h2&gt;
&lt;p&gt;Even though I knew that launching early was vital, I still didn’t want to
“commit” to the final design shortly before the planned go-live. There was always that last bug to fix or that little extra feature to implement.
For example, I wanted to offer two designs&#x2F;layouts: the classic Github contribution timeline and a graph-based design for repositories.
In cases like that, it helps to have a co-founder.
Wolfgang convinced me that multiple layouts were not needed for the MVP and that whatever we’d come up with would probably be wrong anyway without getting early user feedback.
He was right. Without Wolfgang, the shop would probably still not be live today.
We have a much clearer vision now of what people want to see, thanks to launching early. Turns out users were not really interested in the graph-based design after all, and it would have been a waste of time to create it.&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Lesson learned:&lt;&#x2F;strong&gt;
Even if you know all the rules for building products, it’s
different when applying them in practice for the first time. We’ll probably
never be completely happy with the shop functionality, but it’s better to launch
early and make incremental improvements later.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;software-development-is-easy&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#software-development-is-easy&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Software Development Is Easy&lt;&#x2F;h2&gt;
&lt;p&gt;When we started, my main concern was software development. The frontend and the
backend needed to be coded and work together. We didn’t want to run into Github rate-limiting issues in case there were many users on the site. I was also
thinking a lot about which web frontend to use. Should we build it in Rust using
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yewstack&#x2F;yew&quot;&gt;Yew&lt;&#x2F;a&gt; or better go with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gatsbyjs.com&#x2F;&quot;&gt;Gatsby&lt;&#x2F;a&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;Turns out writing the code is the easy part.&lt;&#x2F;p&gt;
&lt;p&gt;Being software engineers, it didn’t take us too long to implement the backend
API and we quickly found a decent template for the frontend. Most of our time
was spent thinking about the product, the user experience,
financing, taxes, the shipping process, marketing, and
integrating customer feedback.
These were all things I had (and still have) little experience in.&lt;&#x2F;p&gt;
&lt;p&gt;Wolfgang suggested to “just use Shopify and the default template” to get started
quickly. In hindsight, it was the absolute right decision. I always thought
Shopify was for simple mom-and-pop stores, but it turns out it’s highly
customizable, integrates well with pretty much anything, and offers excellent tooling
like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;shopify.github.io&#x2F;themekit&#x2F;&quot;&gt;themekit&lt;&#x2F;a&gt;. Payments, refunds,
discounts, customer analytics: it’s all built into the platform. It
saved us sooo much development time.&lt;&#x2F;p&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;twitter.com&amp;#x2F;matthiasendler&amp;#x2F;status&amp;#x2F;1349308007839109122&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;tweet_product.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;tweet_product.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;860&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
&lt;&#x2F;figure&gt;&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Lesson learned:&lt;&#x2F;strong&gt;
There are many &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;datadriveninvestor&#x2F;known-knowns-unknown-knowns-and-unknown-unknowns-b35013fb350d&quot;&gt;unknown
unknowns&lt;&#x2F;a&gt;
— things we are neither aware of nor understand — when starting a project.
Try to get to the root of the problem as soon as possible to save time and avoid
the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Sunk_cost&quot;&gt;sunk cost fallacy&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;users-expect-great-ui-ux&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#users-expect-great-ui-ux&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Users Expect Great UI&#x2F;UX&lt;&#x2F;h2&gt;
&lt;p&gt;Giants like Amazon, Facebook, and Netflix have raised customer
expectations for great UX. They spend millions polishing their websites and getting every detail right. As a result, their sites work &lt;em&gt;just right&lt;&#x2F;em&gt; for millions of customers and on every device.&lt;&#x2F;p&gt;
&lt;p&gt;An indie shop does not have these resources. Nevertheless, many customers expect the same quality user experience as on other sites they use.
Being on the other side of the fence for the first time, I learned how hard it
is to build a user interface that works for 90% of the people. Every little
detail — like the order of form fields — makes a huge difference. Get too
many details wrong, and you lose a customer.&lt;&#x2F;p&gt;
&lt;p&gt;Those things can only be found by watching real users use your product. I promise you, it will be eye-opening!&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Lesson learned:&lt;&#x2F;strong&gt;
Watch potential customers use your service. It will be
painful at first, but will improve the quality of your product. Use standard
frameworks for shops if you can because they get many UI&#x2F;UX details
right out of the box. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;woocommerce.com&#x2F;&quot;&gt;WooCommerce&lt;&#x2F;a&gt; or
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shopify.com&#x2F;&quot;&gt;Shopify&lt;&#x2F;a&gt; come to mind.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;building-products-means-being-pragmatic&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#building-products-means-being-pragmatic&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Building Products Means Being Pragmatic&lt;&#x2F;h2&gt;
&lt;p&gt;We have many ideas for future products. Many friends and customers tell us about
potential features all the time, but the problem is how to prioritize them.
Most ideas won’t work at scale: It’s tricky to find a supplier that has a
product on offer, is cheap, ships worldwide, and has a working integration with
your shop-system. So we have to regularly scrap product ideas, simply
because our suppliers’ support is not there. On top of that, we run the
business next to our day job and other
responsibilities, so we need to make use of our time as efficiently as possible.&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Lesson learned:&lt;&#x2F;strong&gt;
Making services look effortless is hard work. Time is your biggest constraint.
You’ll have to say “no” more often than you can say “yes”.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;whereby.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;whereby.jpg&quot; 
        
            alt=&quot;Due to the pandemic, codeprints was
entirely built remotely. More people should give [whereby](https:&amp;#x2F;&amp;#x2F;whereby.com&amp;#x2F;)
a try.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;395&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Due to the pandemic, codeprints was
entirely built remotely. More people should give &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;whereby.com&#x2F;&quot;&gt;whereby&lt;&#x2F;a&gt;
a try.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;getting-traction-as-a-small-business&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#getting-traction-as-a-small-business&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Getting Traction As A Small Business&lt;&#x2F;h2&gt;
&lt;p&gt;It has never been easier to launch a shop. Services like Shopify, Stripe, and a
host of suppliers make starting out a breeze. On the other hand, there is a lot
more competition now that the barrier to entry is so low.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Thousands&lt;&#x2F;strong&gt; of services are constantly competing for our attention. On top of
that, most customers just default to big platforms like Amazon, AliExpress, or eBay
for their shopping needs these days, and search engines send a big chunk of the traffic there.&lt;&#x2F;p&gt;
&lt;p&gt;Since our product is custom-made, we can not offer it on those bigger platforms.
As an indie shop, we get most visitors through word of mouth, exceptional
customer support, and advertising where developers hang out:
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;KrauseFx&#x2F;status&#x2F;1348546742644580353&quot;&gt;Twitter&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;github&#x2F;comments&#x2F;kvvd3j&#x2F;i_just_got_my_github_contribution_wall_art_from&#x2F;&quot;&gt;Reddit&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=25749287&quot;&gt;HackerNews&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;s&#x2F;b5fbw8&#x2F;create_personal_prints_from_your_github&quot;&gt;Lobste.rs&lt;&#x2F;a&gt;, and friends. It’s essential to focus on
providing value on those platforms; a plain marketing post won’t get you any attention. Other
platforms like LinkedIn, Facebook, ProductHunt, or IndieHackers could also work, but our target audience (OSS developers with an active Github profile) doesn’t
hang out there that much.&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Lesson learned:&lt;&#x2F;strong&gt; Always know where your customers are and understand their needs.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;finding-a-niche-is-only-half-the-job&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#finding-a-niche-is-only-half-the-job&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Finding A Niche Is Only Half The Job&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;startups&#x2F;comments&#x2F;53fynp&#x2F;niche_market_and_peter_thiels_monopoly_theory&#x2F;&quot;&gt;Common market wisdom&lt;&#x2F;a&gt; is to find niche and grow from within. With codeprints we definitely found our niche: the audience is very
narrow but interested in our geeky products. There are 56 million developers on
Github today; that’s a big target audience. Most profiles are not very active,
though. To make a print look attractive, you’d have to consistently commit
code over a long period of time — many years. If we assume that only 1% of
devs are active, that limits our target audience to 560.000 users. That’s still
a big but much smaller market. Now, if only 1% of these people find the shop and
order something (which would be quite a good ratio), we’re looking at 5.600
orders total. Not that much!&lt;&#x2F;p&gt;
&lt;p&gt;In order to extend that audience, one could either increase the number of
potential customers or focus on getting more of the existing potential customers
on the page.
In our case, we expanded by offering a one-year layout, reducing the
required level of Github activity for a cool print. We are also working on making
emptier profiles look more interesting and highlighting the value-producing part
of open source contribution. Every contribution counts — no matter how tiny.&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Lesson learned:&lt;&#x2F;strong&gt;
Make sure that your niche market is not too narrow so that you can make a sustainable business out of it.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;twitter.com&amp;#x2F;orta&amp;#x2F;status&amp;#x2F;1350058678418878465&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;tweet_orta.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;tweet_orta.jpg&quot; 
        
            alt=&quot;Early adopters like [Orta
Therox](https:&amp;#x2F;&amp;#x2F;orta.io&amp;#x2F;) are incredibly precious when starting out. Not
everybody has a rockstar profile like that, though (and that&amp;#x27;s fine).&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;758&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
        &lt;figcaption&gt;
            
            Early adopters like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;orta.io&#x2F;&quot;&gt;Orta
Therox&lt;&#x2F;a&gt; are incredibly precious when starting out. Not
everybody has a rockstar profile like that, though (and that’s fine).
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;make-user-feedback-actionable&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#make-user-feedback-actionable&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Make User Feedback Actionable&lt;&#x2F;h2&gt;
&lt;p&gt;Initial customer feedback is precious. You should focus on every word these
customers say as they believe in your product and want you to win. (They voted
with their wallet after all.) Feedback from
friends is helpful, too, but I usually apply a bigger filter to that. Not all
of my friends are software developers, and while they all mean well, what they
tell me might be different from what they mean. It’s like they
are asking for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hbr.org&#x2F;2011&#x2F;08&#x2F;henry-ford-never-said-the-fast&quot;&gt;faster
horses&lt;&#x2F;a&gt; when what they
really want is a car.
Feedback on social media can be… snarky at times; be prepared for that! Your job
is to find the grain of truth in every statement and focus on constructive
advice.&lt;&#x2F;p&gt;
&lt;p&gt;For example, take &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;github&#x2F;comments&#x2F;kvvd3j&#x2F;i_just_got_my_github_contribution_wall_art_from&#x2F;gj1g015?utm_source=share&amp;amp;utm_medium=web2x&amp;amp;context=3&quot;&gt;this feedback&lt;&#x2F;a&gt; we got:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;How lazy can someone be to pay €36 for this.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;You could turn it around to make it constructive:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Can I get a cheaper version to print myself?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And that is some valuable feedback. We could provide a downloadable version in
the future!&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;&lt;strong&gt;Lesson learned:&lt;&#x2F;strong&gt;
It takes practice to extract actionable feedback from user input and make it fit your product vision.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;summary&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#summary&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;2020 was a crazy year.
I helped launch two small side-businesses, codeprints and
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2020&#x2F;sponsors&#x2F;&quot;&gt;analysis-tools.dev&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Both have an entirely different revenue model, but
they have one thing in common: they were &lt;strong&gt;super fun&lt;&#x2F;strong&gt; to build! 🤩
It’s motivating to look back at those achievements sometimes…
That print of 2020 pretty much encapsulates those feelings for me.
(Note the greener spots in August and September, which is when we launched
analysis-tools and the days in December when we built codeprints.)&lt;&#x2F;p&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;codeprints.dev&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;vertical.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;codeprints&amp;#x2F;vertical.jpg&quot; 
        
            alt=&quot;My coding year in review using our new
vertical layout.&amp;lt;br &amp;#x2F;&amp;gt;Here&amp;#x27;s to
building more products in 2021.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;1029&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
        &lt;figcaption&gt;
            
            My coding year in review using our new
vertical layout.&lt;br &#x2F;&gt;Here’s to
building more products in 2021.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Let me know if you found that post helpful and reach out if you have questions.
Oh and if you’re looking for a unique way to decorate your home office, why not
get your own print from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;codeprints.dev&quot;&gt;codeprints&lt;&#x2F;a&gt;? 😊&lt;&#x2F;p&gt;
&lt;p&gt;P.S.: If you’re a product owner and you’re looking for a unique present for your
team, &lt;a href=&quot;mailto:support@codeprints.dev?subject=codeprints%20for%20teams&amp;amp;body=Hi%20there&quot;&gt;get in contact&lt;&#x2F;a&gt; and be the first to get an invite to a private beta.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>So You Want To Earn Money With Open Source</title>
        <published>2021-01-04T00:00:00+00:00</published>
        <updated>2021-01-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2021/oss-money/"/>
        <id>https://endler.dev/2021/oss-money/</id>
        
        <content type="html" xml:base="https://endler.dev/2021/oss-money/">&lt;p&gt;I earned 0 Euros from maintaining OSS software for years, and I thought that’s
the way things are. I finally looked into ways to monetize my projects last year
and in this talk I want to share what I learned so far. It didn’t make me
rich (yet!), but I built my first sustainable side-project with
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;analysis-tools.dev&#x2F;&quot;&gt;analysis-tools.dev&lt;&#x2F;a&gt; ✨.&lt;&#x2F;p&gt;
&lt;p&gt;I’ll talk about this and other projects and the mistakes I made on the road
towards sustainability.&lt;&#x2F;p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;NlKuICiT470&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;maxresdefault.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;maxresdefault.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;p&gt;Related links and resources:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Podcast by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;calebporzio.com&#x2F;&quot;&gt;Caleb Porzio&lt;&#x2F;a&gt; about why building
a business around Github sponsors is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;podbay.fm&#x2F;p&#x2F;building-livewire&#x2F;e&#x2F;1593614940&quot;&gt;so
hard&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;The Changelog Podcast — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;changelog.com&#x2F;podcast&#x2F;405&quot;&gt;It’s OK to make money from your open source&lt;&#x2F;a&gt;
with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zenorocha.com&#x2F;&quot;&gt;Zeno Rocha&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nadia.xyz&#x2F;&quot;&gt;Nadia Eghbal&lt;&#x2F;a&gt; talking about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=TMxBf-Ohgmg&quot;&gt;Maintenance of our essential info-structure&lt;&#x2F;a&gt;. She also wrote a book on that topic
called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;3vAl43v%22&quot;&gt;Working in Public&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vadimdemedes.com&#x2F;posts&#x2F;generating-income-from-open-source&quot;&gt;Generating income from open source&lt;&#x2F;a&gt; by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;vadimdemedes&quot;&gt;Vadim Demedes&lt;&#x2F;a&gt;, which explains different ways to monetize your projects based on various real-world examples.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Find a full transcript of the talk below. (Sorry for the wall of text.)&lt;&#x2F;p&gt;
&lt;hr &#x2F;&gt;
&lt;p&gt;This is my talk about earning money with Open Source, which I gave at the Web
Engineering Meetup Aachen at the end of 2020. The organizers gladly allowed me
to share it on my YouTube channel. I’m basically trying to answer the question:
“Why am I not making 100k on Github?”. I’m talking about finding corporate
sponsors for myself and the long road towards sustainability of open-source
maintenance.&lt;&#x2F;p&gt;
&lt;p&gt;You might not even want to start. This is a talk for those people that have
the mindset that it’s probably not worth it to spend that much effort on Open
Source if it takes so long until you find success. Now, this talk turned out to
be a little grim. I had this very motivational talk in mind, but in reality,
it’s hard, and by hard, I mean it’s really hard.&lt;&#x2F;p&gt;
&lt;p&gt;I just want to get this point across and maybe still motivate you to do it but
first: why am I entitled to talk about this? I’ve been doing Open Source for 10
years over 10 years now. This is a talk dedicated to my former self maybe 15
years ago. I work at trivago, which is a hotel search company based in
Düsseldorf. I have a blog at endler.dev. Like everyone and their mom, I also
have a YouTube channel. It’s called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;hello-rust&#x2F;&#x2F;&quot;&gt;Hello, Rust!&lt;&#x2F;a&gt; and I’m
extremely active with one video every two years. Hence, you definitely want to
subscribe to not miss any updates. But today, I want to talk about Open Source,
and I have a very sophisticated outline with two points my journey and revenue
models.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s go back all the way to 2010. The world definitely looked a bit different
back then.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;oss-money&amp;#x2F;github.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2021&amp;#x2F;oss-money&amp;#x2F;github.jpg&quot; 
        
            alt=&quot;Github in 2010&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;331&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Github in 2010
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;This was Github, and I was a bit late to the game. I joined in January 2010, and
by then, Github was already two years old, so my username was taken. I usually
go by the handle &lt;code&gt;mre&lt;&#x2F;code&gt; on platforms, and I noticed that this handle was not
used by anyone, so I just sent a mail to support and asked if I could have it,
and then I got an answer from this guy saying “go for it.” It was Chris
Wanstrath, who goes by the handle defunct, and he’s the former CEO of Github,
and at this point in time, I was hooked. I really liked the platform. I really
liked how they worked very hands-on with Open Source. I used it for some
projects of mine; you can see in the screenshot that I uploaded my blog, for
example, because they host it for free. It was built with Jekyll, and you just
push it to their site. Then they statically generate it, and it’s done. It goes
without saying that nothing has changed in the last 10 years because my blog
more or less still looks like that. It’s not built with jQuery and Jekyll
anymore, but with zola and Cloudflare Worker Sites, but it’s more or less the
same thing. For preparing for this talk, I wanted to take a step back and see
where I was coming from and where I am right now, and probably the best way to
do it is to look up some statistics and see if the number of repositories over
time would give me some insights. So I queried the Github API for that.&lt;&#x2F;p&gt;
&lt;p&gt;You can see it’s pretty much a linear graph from 2010 all the way to 2020.
Except for 2018, where I reached peak productivity, it seems, but oh well. In
the end, it’s more or less a linear thing, and you might say you put some work
in you get some feedback out, but in reality, it’s different. There is a
compound effect. If we look at my number of stars over time, you can see that
more or less it started very slowly, and now it’s sort of growing exponentially,
so right now, we are at 25.000 stars across all projects. Another way to look at
it would be the number of followers. That’s kind of a new metric to me, but I
did look up some statistics from archive.org (because Github doesn’t have that
information through their API), and again, it’s more or less exponential growth.&lt;&#x2F;p&gt;
&lt;p&gt;You put some work in, but you get a compound effect of your work plus some
interest out. This is not luck; it’s work. It means you know what you’re doing.
At the same time, there’s the elephant in the room, and that is it’s just a pat
on the back. We have earned zero dollars until now, and one question you might
have is how do you monetize this effort.&lt;&#x2F;p&gt;
&lt;p&gt;First off, is it an effort?&lt;&#x2F;p&gt;
&lt;p&gt;Well, I don’t know about you, but I probably spend two or three hours on average
per day on Open Source: thinking about Open Source and creating new projects,
but also maintaining and code review, so it really is work, and it’s a lot of
work, and you more or less do that for free.&lt;&#x2F;p&gt;
&lt;p&gt;There’s nothing wrong with doing things for free and doing it as a hobby, but in
this case, you are supposed to be working on whatever you like. Open Source is
not like that; sometimes you have obligations, and you feel responsible for
maybe helping people out, which is a big part of it. You do that next to your
regular work, so it can really be a burden. If you don’t know by now, making
this somehow valuable is hard, it’s really hard. I want to talk about some ways
to build a proper revenue model from Open Source. It goes without saying that
this should probably not be your first focus if you saw the graphs before, but
once you reach a point where you want to get some revenue, you have a couple of
options. I don’t want to talk about doing Open Source as part of your business,
and I don’t want to talk about bigger companies and more significant support
here. I want to focus on a couple things that everyone can do. Sponsoring [on
Github] is one. Offer paid learning materials on top of your normal
documentation. For example, you might have a video series that you ask for
money. Sell merchandising like Mozilla does. Consulting next to your Open Source
business Services and plugins like writing an ADFS plugin or high availability
functionality are very common examples for paid features targeting enterprises.&lt;&#x2F;p&gt;
&lt;p&gt;But let’s start with the basics. Let’s start with point number one, sponsoring.
There are two types of sponsoring: the first one is individual donations.
Individual sponsoring is what Github Sponsors is all about. If you want to earn
money [with that model], you have to think about the funnel, and you have to
think about how you capture people’s attention and how you monetize that. It
starts with a product, [which] can be anything. From there, you generate
interest, and this interest creates an audience, and that audience eventually
might pay for your service, and this is actually the entire secret. It’s how you
earn money with any product, and with Open Source, if you want to attract
sponsors, you build a product people want.&lt;&#x2F;p&gt;
&lt;p&gt;If you transfer that to Open Source, building a project is maybe a repository,
and the stars indicate the interest of the audience. The audience itself is made
out of followers (personal followers or followers of a company), and those
followers might or might not become sponsors in the end. Now, I know stars are a
terrible metric for popularity because some people use stars differently than
others. For example, some use it as bookmarks to check out projects later,
others want to thank the developers for maybe putting in a lot of effort, and so
on, but it’s a good first estimation.&lt;&#x2F;p&gt;
&lt;p&gt;Now, think about the following. Think about the number of stars I have and the
followers and the number of sponsors. Think about my “funnel” right now. I told
you that I have 25.000 stars and roughly 1000 followers, and out of those, I
have three sponsors, so the ratio between the stars and sponsors is 0.01. That
looks pretty grim. It means you need around 8.000 stars to attract a single
supporter. I was wondering: “maybe it’s just me?”. Maybe the top 1000 Github
maintainers did not have that problem. Well, it turns out it’s exactly the same
schema. If you take the top 1000 Github maintainers and look at their sponsors,
it’s again a pretty grim picture. For example, looking at the median, you look
at 3421 followers per person and a median of zero sponsors. That’s zero percent
if my math is correct, and if you look at the average, you even have 5430
followers (because Linus Torvalds pushes that number up). You have 2.8 sponsors
out of that on average, and that is 0.5%, which is a bit more than I have, but
it’s roughly in the same ballpark. Now think about this: Github has 40 million
users, so that means the top 1000 maintainers make up 0.0025% of the entire
community. The median income of those maintainers on Github is basically zero.&lt;&#x2F;p&gt;
&lt;p&gt;That in and on itself is maybe not the biggest problem, but keep in mind that
the Github revenue of 2019 was 300 million dollars. I read that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=23219251&quot;&gt;comment on
Hacker News&lt;&#x2F;a&gt; yesterday:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have sponsors on Github and rake in a cool two dollars per month. It’s
obviously less after taxes, so I have to have a day job.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;So this is clearly not working. You have to think of different ways to monetize
Open Source, or you just wait until Github Sponsors becomes more popular –
whatever happens first. One way I just want to quickly touch on is the notion of
sponsorware. It’s kind of a new concept, and some people haven’t heard of it
before. I honestly really like it. Generally speaking, you create a project, and
you keep it private. You talk about it on Twitter, though or any other platform,
and you say: “hey, I’m building this, but if you want early access, you have to
become a sponsor,” and once you reach a certain threshold of sponsored sponsors,
or income or whatever. Then you make a project public. This initial example that
I showed you, where someone was earning 100k on Open Source, is from someone
doing just that. He’s building products and services, talks about them, and then
makes them open for everyone in the end.&lt;&#x2F;p&gt;
&lt;p&gt;This has some advantages: first of you get early feedback from people that
really believe in your mission. Second, you don’t have to work for free all the
time, and third, you might also create an audience and hype from your projects.
The disadvantage is that if you are a hardcore Open Source or free software
believer, this goes against your ethic. You want the software to be open, to
begin with, without any additional requirements. So you really have to make up
your own mind about that. I tried, and I have an early access program, which I
only share with sponsors. [My first sponsorware was a] tool for getting Github
statistics. [The statistics from this talk were] created with that tool. I think
you need a big audience to pull that off. The question is if you want to put
that much effort in, or you just want to make it open in the first place and
think about other revenue models. However, I think still it’s a very interesting
concept, and we might see that [more] in the future, so you know how it looks
like now, and you have a name for it.&lt;&#x2F;p&gt;
&lt;p&gt;Another one is corporate sponsoring. This is a double-edged sword because
corporate sponsoring means that a company gives you money and sometimes wants
something. They might want additional support, or they want the bug to be fixed,
and more or less it feels like you are somehow beginning to work for them, but
nevertheless, those companies put in quite a big amount of money into Open
Source these days. Looking at two big companies, Facebook and Google, they
invested 177k and 845k respectively into Open Source over their lifetime on Open
Collective, a platform for collecting those donations. That’s really great. We
need more companies doing that, but also, as a little side note and maybe as a
little rant, I believe that those companies are doing way too little.&lt;&#x2F;p&gt;
&lt;p&gt;Facebook’s revenue last year was 70 billion, and Google had 160 billion, which
is nothing to be ashamed of, so I wonder really if this is the most they can do.
Of course, Google, for example, also donated to other projects like Mozilla, and
they also organize meetups and so on. But do you really think that Facebook and
Google would exist today if there was no Python or web server or Linux back in
the day when two Stanford students tried to build a search engine? Sometimes I
feel that Fortune 500 companies really don’t understand how much they depend on
Open Source and how many people depend on a few people who maintain critical
parts of our infrastructure.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t think they invest nearly enough into Open Source. What a lot of people
think is that Open Source works like the panel on the left where you have a full
room of engineers trying to figure out the best way to build a project, and in
reality, it’s more or less someone working late at night to fix bugs and doing
it because they believe in it. The public perception is probably wrong, and a
really small group of people who maintain critical infrastructure. Sometimes
that can lead to very tricky situations. Two of my childhood heroes talked about
it openly: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20221024021910&#x2F;https:&#x2F;&#x2F;kennethreitz.org&#x2F;&quot;&gt;Kenneth
Reitz&lt;&#x2F;a&gt; is
the core maintainer of requests for Python and &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;invece.org&#x2F;&quot;&gt;antirez&lt;&#x2F;a&gt; is
the creator of
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;redis.io&#x2F;&quot;&gt;Redis&lt;&#x2F;a&gt;, a key-value store. So one is front-end development
and the other one from backend-end. They both talk about burnout here because
the burden of becoming an Open Source maintainer on a big scale can very much
and very quickly lead to burnout. The internet never sleeps. You never go to
sleep. You always get a ticket, a feature request, a pull request, an issue. You
always have something to work on, and on top of that, you have to do all your
other responsibilities, so that can lead to burnout really quickly. There was
one guy who I also respect deeply. His name is Mark Pilgrim. He is the author of
Dive Into Python, and he once pulled a 410 for deleting everything [about him]
on the internet. There’s actually a term for it: infocide for “information
suicide.” He got fed up with the ecosystem, and if you think about the Ruby
community, you might remember _why, the author of the Poignant Guide to Ruby.
He did kind of the same thing. Focusing on what antirez has said, “once I
started to receive money to work at Redis, it was no longer possible for my
ethics to have my past pattern, so I started to force myself to work on the
normal schedules. This, for me, is a huge struggle for many years. At this
point, moreover, I’m sure I’m doing less than I could, because of that, but this
is how things work”, so it feels like he feels guilty for maybe being forced
into that work schedule and maybe not performing well enough. There are some
signs of burnout for me somehow, and it’s that love-hate relationship of Open
Source and money. If you accept money, it becomes a job, but you’re not writing
code most of the time. You’re writing the talks, reviewing pull requests, you’re
looking at issues, you’re answering questions on StackOverflow, you’re
discussing on Discord, you’re marketing on YouTube or conferences. When you
become popular with Open Source, then it feels like you have a choice between
two options: one is depression and the other one is burnout. If your project
does not become successful, then suddenly you think you’re a failure, you’re a
mistake. It has zero stars; nobody likes it. But if it becomes a success, then
everyone likes it, and you get hugged to death. That’s a really unfortunate
situation to be in, and you want to stop being overwhelmed with those
responsibilities. You have to set clear boundaries and pick your poison. You
have to be careful if you accept companies as sponsors. I want to show you one
example of how it can work and [point out] some risks. Earlier this year, I
started working on a real project that I had been putting off for many years
before.&lt;&#x2F;p&gt;
&lt;p&gt;You see, in December 2015, I started a list of static analysis tools on Github.
Static analysis tools are just tools that help you improve your code, and it
turns out that there’s a lot of those tools. Just starting to collect them was
the first step. I didn’t think much about it, but over time that became really
popular. And you can see that this graph is more or less a linear increase in
stars over time. In 2018, I started really thinking hard about whether there was
more than just a Github project here. I talked to many people that I had this
idea of building something more from that. It really took someone else to maybe
push me over the finishing line and convinced me that this was worth it, and
that is Jakub. He said, “why not build a website from it?” and over the course
of maybe two weekends or so, we built a website. It’s built with Gatsby, but it
really doesn’t matter. We just did it, and then we saw what happened to it. We
render 500 tools right now, and the initial feedback was really great. People
really seem to like that. We got a cool 720.000 requests on the first day, and
over the next week or so, it more or less hit 1.5 million. That was great
because suddenly people started getting interested in that project. So we
started finding some sponsors. Those companies are special because they believe
in your mission, but they also know how Open Source works. They don’t really
expect you to advertise their tool. They want to sell to developers, so they
want to be in the developers’ minds, saying: “Hey! You are a developer. We built
this amazing tool you might want to check it out!” but they also get seen as an
Open Source company. I think that’s a win-win. I have to say it doesn’t always
go as easily. sometimes companies expect you to just have cheap advertising
space. Then they jump off the moment they see you don’t get that many clicks,
but others understand that they invest into something that maybe pays off in a
year or two from now. So I’m really thankful that some companies understand that
mission. However, what companies want is different than what individuals want.
Companies want an invoice. Companies want something tax-deductible. Companies
want someone that keeps the lights on and is responsive via email, so you really
have those obligations, and one platform that helps with that is Open
Collective. They have a 501c6 program for Open Source projects that acts as a
fiscal host, which means they will do all the invoicing and officially be the
maintainers. If you, as an Open Source maintainer or a contributor to a project,
want to get [reimbursed for your work], you have to send an invoice to open
collective.&lt;&#x2F;p&gt;
&lt;p&gt;I think that’s the best of both worlds. Again, because it’s a very transparent
process, companies are in the loop and don’t have to deal with all the financial
stuff. But it also means that you have to really polish your public perception.
Companies really want to know what they can get out of sponsoring you, and you
have to make that very clear. Probably the most important site that you have is
not your website, but it’s your sponsors page on Github where you describe the
different tiers and what those tiers mean, so we have three tiers: One is
targeted at smaller companies and freelancers. They just get exposure, and they
get seen as an Open Source friendly tech company. That is a hundred dollars a
month. We have a middle-tier, a company sponsor that maybe is a bigger company.
They get the batch, too, but they also get a blog post about a static analysis
tool that they want to promote, but we make it transparent that this is really a
sponsored content. Finally, if you want to go all the way, you go to full
content creation, which might be a video workshop, but we don’t have video
workshop sponsors yet, so I cannot talk about that yet. I have to say I really
would like to try though and it’s cheap really for what you get.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, those are things that you can do today. Without really changing how you
work on Open Source, you can set that up, and you just see how it goes. Maybe no
one reacts, and that’s fine. Everything else on that list is kind of advanced.
You need an audience, and so you should start with that.&lt;&#x2F;p&gt;
&lt;p&gt;Paid learning material is something that we are doing with analysis tools in the
future with a video course. There are companies like tailwind that do that
impressively well, so you can learn from them. For merchandising, you have to
have a brand. Hence, it’s not something that I could do, but someone like
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;mozilla.org&#x2F;&quot;&gt;Mozilla&lt;&#x2F;a&gt; or the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;thecodingtrain.com&#x2F;&quot;&gt;Coding Train&lt;&#x2F;a&gt; on
YouTube could definitely do something like that. Consulting is always an option.
Still, it’s also a lot more work and probably takes you away from what you
really love, so it really becomes a job. You have to think about whether you
want to do that or not. Enterprise services are very advanced [and interesting]
for maybe the one percent of projects that can be run in a business and where
you have special requirements. I have to say start from the top and work your
way down. Start to create an audience. It’s probably easier to build an audience
on Twitter and then funnel it back to Github than the other way around. Oh, by
the way, did I tell you it’s hard? I really don’t want to end on a low note. I
really want to emphasize that I would do it again, all of that if I started
today. I think there’s no better time to contribute to Open Source than today.
Probably tomorrow will even be a better time because suddenly, way more people
are interested, it’s way easier to set up projects, you have all those free
tools like VSCode and Github actions, free hosting. It’s just amazing how much
you can pull off with very little money involved. So you can try it. What’s the
worst thing that can happen? No one cares? Well, okay, then you’re as good as
me. But I have some tips for you if you want to start today. My first tip is:
“do your homework.” Many people start with learning, and then they build things,
and then they close the circle, but there’s one key piece missing here. Some
people hate the word, but you learn to love it eventually. It’s called
marketing. Marketing means a lot of things to a lot of people, but what it means
to me is getting the word out because someone else will if you don’t, and you
are awesome; you just have to realize that. Maybe not everyone knows [about your
project] right away, so you should really talk about it more. Maybe at
conferences, maybe on Twitter, maybe you can just tell your friends. Maybe you
can ask people to contribute and to support you. Somehow it’s frowned upon in
the community that if you do marketing, you’re not doing it for real, but I
think that’s not true. I think that if smart people and patient and passionate
people did marketing, then the world would be a better place; because I’m pretty
sure the evil guys do marketing. So do your homework, but rest assured that
being an Open Source maintainer means running a business, and you are the
product. You have to think about why someone would want to sponsor you because
if you don’t come up with an answer for that, how should they know. Also, think
about the funnel. How will people find you, for example? The best way for people
to find you is probably starting a YouTube channel.&lt;&#x2F;p&gt;
&lt;p&gt;There are easier ways, though.&lt;&#x2F;p&gt;
&lt;p&gt;[First,] you can always help out in a different project, and you
don’t even have to be a coder. If you are good with design, then I can tell you
there are so many Open Source projects that need designers. It’s crazy.
Maybe start creating a logo for a small project and start getting some
visibility. Another one is having fun. If you know that earning money is hard in
Open Source, then that can also be liberating because it means you can
experiment and you can be creative, and yeah, having fun is the most important
thing, I guess.&lt;&#x2F;p&gt;
&lt;p&gt;Second, build things you love because it’s your free time in the end. The
chances that someone will find the project is pretty low, so it better be
something that you’re really interested in. If you don’t believe in that, just
move on to the next thing. It’s fine if you drop a project that you don’t
believe in anymore. No one will hold you accountable for that unless they are
jerks, and you don’t want to be surrounded by jerks.&lt;&#x2F;p&gt;
&lt;p&gt;Third, find friendly people because you really grow with your community. You
want people that support your project and maybe eventually become maintainers to
ease the burden, and that takes a lot of time, sometimes years, until you find
one maintainer, so always be friendly, try to put yourself in their perspective.
Go the extra mile if you can. For example, reintegrate the master branch into
their pull request. Just do it for them. Say thanks twice if you’re unsure.&lt;&#x2F;p&gt;
&lt;p&gt;Fourth is to grow an audience.&lt;br &#x2F;&gt;
Radical marketing is one way, but being approachable and being inclusive is
another way. You want to be the guy or the girl that people go to when they have
a tough question, or they want to know how to get into Open Source. You want to
be the person that helps them out on their first pull request. They will pay it
back a thousand times. The most exciting people I have met so far are available
for questions, and they don’t really ask for anything in return. You hold them
very close and dear to your heart. When the time comes, you will remember those
people. We will say, like, “this is an amazing person to work with; I can highly
recommend them,” which is called a lead.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, be in it for the long run. Good things take time. You see, it took me
10 years. Maybe it takes you five or maybe even less, but it’s probably not an
overnight success. It’s really a long-term investment.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>My Blog Just Got Faster: Cloudflare Workers and AVIF Support</title>
        <published>2020-09-14T00:00:00+00:00</published>
        <updated>2021-04-14T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2020/perf/"/>
        <id>https://endler.dev/2020/perf/</id>
        
        <content type="html" xml:base="https://endler.dev/2020/perf/">&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;hero.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;hero.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;350&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;Did I mention that this website is fast?
Oh yeah, &lt;a href=&quot;&#x2F;2019&#x2F;tinysearch&#x2F;&quot;&gt;I did&lt;&#x2F;a&gt;, &lt;a href=&quot;&#x2F;2017&#x2F;image-previews&#x2F;&quot;&gt;multiple times&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Few reasons (from ordinary to the first signs of creeping insanity):&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;📄 Static site&lt;&#x2F;li&gt;
&lt;li&gt;☁️ Cached on Cloudflare CDN&lt;&#x2F;li&gt;
&lt;li&gt;🔗 ️HTTP&#x2F;2 and HTTP&#x2F;3 support&lt;&#x2F;li&gt;
&lt;li&gt;🚫 No web fonts (sadly)&lt;&#x2F;li&gt;
&lt;li&gt;✅ &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jorgelbg.me&#x2F;dashflare&#x2F;&quot;&gt;Edge-worker powered analytics&lt;&#x2F;a&gt; (no Google Analytics)&lt;&#x2F;li&gt;
&lt;li&gt;🌸 Avoiding JavaScript whenever possible; CSS covers 90% of my use-cases.&lt;&#x2F;li&gt;
&lt;li&gt;🖼️ Image width and height specified in HTML to avoid page reflows.&lt;&#x2F;li&gt;
&lt;li&gt;👍🏻 Inlined, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jakearchibald.github.io&#x2F;svgomg&#x2F;&quot;&gt;optimized SVG graphics&lt;&#x2F;a&gt; and hand-rolled CSS&lt;&#x2F;li&gt;
&lt;li&gt;🚅 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tinysearch&#x2F;tinysearch&quot;&gt;Static WASM search&lt;&#x2F;a&gt; (lazy loaded)&lt;&#x2F;li&gt;
&lt;li&gt;🏎️ The entire homepage is &amp;lt;10K (brotli-compressed), including graphics, thus should fit into the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.tunetheweb.com&#x2F;blog&#x2F;critical-resources-and-the-first-14kb&#x2F;&quot;&gt;first HTTP round-trip&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;💟 Heck, even the favicon is optimized for size. Update: I’m using an SVG icon now thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;austingil.com&#x2F;svg-favicons&#x2F;&quot;&gt;this article&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Then again, it’s 2020: &lt;strong&gt;everyone&lt;&#x2F;strong&gt; is optimizing their favicons, right? &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.p01.org&#x2F;defender_of_the_favicon&#x2F;&quot;&gt;…right!?&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Well, it turns out most other sites don’t think about their user’s data plans as much as I do. Actually, that’s an understatement: they don’t care at all. But to me, &lt;strong&gt;lean is beautiful&lt;&#x2F;strong&gt;!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wait-what-about-images&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#wait-what-about-images&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Wait, What About Images?&lt;&#x2F;h2&gt;
&lt;p&gt;I prefer SVG for diagrams and illustrations.
Only if it’s a photo, I’ll use JPEG or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;speed&#x2F;webp&#x2F;&quot;&gt;WebP&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To be honest with you, I never really liked WebP.
The gist is that it might not even be smaller than JPEGs compressed with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;siipo.la&#x2F;blog&#x2F;is-webp-really-better-than-jpeg&quot;&gt;MozJPEG&lt;&#x2F;a&gt;.
There is a lengthy &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bugzilla.mozilla.org&#x2F;show_bug.cgi?id=856375&quot;&gt;debate on the Mozilla bug tracker&lt;&#x2F;a&gt; if you want to read more.
To this day, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caniuse.com&#x2F;?search=webp&quot;&gt;Safari doesn’t support WebP&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hello-avif-wave&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#hello-avif-wave&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Hello AVIF 👋&lt;&#x2F;h2&gt;
&lt;p&gt;Meet &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aomediacodec.github.io&#x2F;av1-avif&#x2F;&quot;&gt;AVIF&lt;&#x2F;a&gt;, the new next-gen image compression format. Check this out:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;stats.svg&quot; 
        
            alt=&quot;[ReachLightSpeed.com](https:&amp;#x2F;&amp;#x2F;reachlightspeed.com&amp;#x2F;blog&amp;#x2F;using-the-new-high-performance-avif-image-format-on-the-web-today&amp;#x2F;)&quot;
        

        

        
        
        
            width=&quot;768&quot;
        
        
            height=&quot;216&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;reachlightspeed.com&#x2F;blog&#x2F;using-the-new-high-performance-avif-image-format-on-the-web-today&#x2F;&quot;&gt;ReachLightSpeed.com&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;It’s already supported by Chrome 85 and Firefox 80.&lt;br &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=BixwVsiDdZM&quot;&gt;Then it hit me like a hurricane&lt;&#x2F;a&gt; 🌪️:&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;😲 Holy smokes, AVIF is supported by major browsers now!?&lt;br &#x2F;&gt;
I want this for my blog!&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Yes and no.&lt;&#x2F;p&gt;
&lt;p&gt;I’m using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt; for my blog, and
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;image-rs&#x2F;image&#x2F;issues&#x2F;1152&quot;&gt;AVIF support for Zola&lt;&#x2F;a&gt; is not yet there, but I want it now!
So I whipped up an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;endler.dev&#x2F;blob&#x2F;master&#x2F;helpers&#x2F;img&#x2F;src&#x2F;main.rs&quot;&gt;ugly Rust script&lt;&#x2F;a&gt; (as you do) that creates AVIF images from my old JPEG and PNG images. I keep the original raw files around just in case.&lt;&#x2F;p&gt;
&lt;p&gt;Under the hood, it calls &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kornelski&#x2F;cavif&quot;&gt;cavif&lt;&#x2F;a&gt; by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kornelski&quot;&gt;Kornel Lesiński&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;data-savings&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#data-savings&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Data Savings&lt;&#x2F;h2&gt;
&lt;p&gt;The results of AVIF on the blog were nothing short of impressive:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;own_stats.svg&quot; 
        
            alt=&quot;Total image size for [endler.dev&amp;#x2F;2020&amp;#x2F;sponsors](https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors)&quot;
        

        

        
        
        
            width=&quot;768&quot;
        
        
            height=&quot;156&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            Total image size for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2020&#x2F;sponsors&quot;&gt;endler.dev&#x2F;2020&#x2F;sponsors&lt;&#x2F;a&gt;
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;check-your-browser&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#check-your-browser&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Check Your Browser&lt;&#x2F;h2&gt;
&lt;p&gt;But hold on for a sec… is your browser even capable of showing AVIF?&lt;&#x2F;p&gt;
&lt;picture&gt;
  &lt;source srcset=&quot;avif_supported.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
  &lt;img src=&quot;avif_not_supported.jpg&quot; &#x2F;&gt;
&lt;&#x2F;picture&gt;
&lt;p&gt;If that reads “yup,” you’re all set.&lt;br &#x2F;&gt;
If that reads “nope,” then you have a few options:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;On Firefox&lt;&#x2F;strong&gt;: Open &lt;code&gt;about:config&lt;&#x2F;code&gt; from the address bar and search for &lt;code&gt;avif&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;On Chrome&lt;&#x2F;strong&gt;: Make sure to update to the latest version.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;On Safari&lt;&#x2F;strong&gt;: I’m not sure what you’re doing with your life. Try a real browser instead. 😏&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;workaround-i-fallback-for-older-browsers&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#workaround-i-fallback-for-older-browsers&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Workaround I: Fallback For Older Browsers&lt;&#x2F;h2&gt;
&lt;p&gt;HTML is great in that your browser ignores unknown new syntax.
So I can use the &lt;code&gt;&amp;lt;picture&amp;gt;&lt;&#x2F;code&gt; element to serve the right format to you. (Look ma, no JavaScript!)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;picture&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;source&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; srcset&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fancy_browser.avif&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;source&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; srcset&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;decent_browser.webp&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;img&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;meh_browser.jpg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;picture&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;endler.dev&#x2F;blob&#x2F;master&#x2F;templates&#x2F;shortcodes&#x2F;figure.html&quot;&gt;The real
thing&lt;&#x2F;a&gt;
is a bit more convoluted, but you get the idea.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;workaround-ii-wrong-content-type-on-github-pages&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#workaround-ii-wrong-content-type-on-github-pages&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Workaround II: Wrong Content-Type On Github Pages&lt;&#x2F;h2&gt;
&lt;p&gt;There was one ugly problem with Github and AVIF, though: Their server returned a
&lt;code&gt;Content-Type: application&#x2F;octet-stream&lt;&#x2F;code&gt; header.&lt;&#x2F;p&gt;
&lt;p&gt;This meant that the images &lt;em&gt;did not load&lt;&#x2F;em&gt; on Firefox.&lt;&#x2F;p&gt;
&lt;p&gt;There is no way to fix that on my side as Github is hosting my page. Until now!
I wanted to try Cloudflare’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;workers.cloudflare.com&#x2F;sites&quot;&gt;Workers Sites&lt;&#x2F;a&gt; for a long time, and this bug
finally made me switch. Basically, I run the full website as an edge worker
right on the CDN; no own web server is needed. What’s great about it is that
the site is fast &lt;em&gt;everywhere&lt;&#x2F;em&gt; now — even in remote locations — no more
roundtrips to a server.&lt;&#x2F;p&gt;
&lt;p&gt;By running an edge worker, I also gained full control over the request- and response objects.
I added &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;endler.dev&#x2F;blob&#x2F;1f142c14ab40ca264c4c8c599a5db6b91ca9cbaa&#x2F;workers-site&#x2F;index.js#L53-L56&quot;&gt;this gem&lt;&#x2F;a&gt; of a snippet to intercept the worker response:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string z-regexp&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\.&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-regexp z-js z-string z-regexp&quot;&gt;avif&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-keyword z-control z-anchor z-regexp&quot;&gt;$&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string z-regexp&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;test&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;headers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;set&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Content-Type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;image&#x2F;avif&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;headers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;set&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Content-Disposition&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;inline&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-brace z-round&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And bam, Bob’s your uncle. Firefox is happy.
You can read more about modifying response objects &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.cloudflare.com&#x2F;workers&#x2F;examples&#x2F;modify-response&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Another side-effect of Workers Sites is that a production deployment takes &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;endler.dev&#x2F;actions&quot;&gt;one minute&lt;&#x2F;a&gt; now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance-results-after-moving-to-cloudflare&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#performance-results-after-moving-to-cloudflare&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Performance Results After Moving To Cloudflare&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;cdn_before.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;cdn_before.jpg&quot; 
        
            alt=&quot;Website response time before&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;511&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Website response time before
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.keycdn.com&#x2F;performance?url=https:&#x2F;&#x2F;endler.dev&quot;&gt;KeyCDN&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;cdn_after.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;cdn_after.jpg&quot; 
        
            alt=&quot;Website response time after&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;511&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Website response time after
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.keycdn.com&#x2F;performance?url=https:&#x2F;&#x2F;endler.dev&quot;&gt;KeyCDN&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;pingdom_before.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;pingdom_before.jpg&quot; 
        
            alt=&quot;Page size and rating before&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;214&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Page size and rating before
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.pingdom.com&#x2F;#5d1d402401400000&quot;&gt;Pingdom.com&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;pingdom_after.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;pingdom_after.jpg&quot; 
        
            alt=&quot;Page size and rating after&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;214&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Page size and rating after
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tools.pingdom.com&#x2F;#5d226db3af800000&quot;&gt;Pingdom.com&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I don’t have to hide from a comparison with well-known sites either:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;speedcurve.png&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;perf&amp;#x2F;speedcurve.png&quot; 
        
            alt=&quot;Comparison with some other blogs I read&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;440&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Comparison with some other blogs I read
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;speedcurve.com&quot;&gt;Speedcurve&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;further-reading&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#further-reading&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Further reading&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;reachlightspeed.com&#x2F;blog&#x2F;using-the-new-high-performance-avif-image-format-on-the-web-today&#x2F;&quot;&gt;How to Use AVIF: The New Next-Gen Image Compression Format&lt;&#x2F;a&gt; — Nice introduction that highlights some common pitfalls when integrating AVIF. It inspired me to add AVIF support.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jakearchibald.com&#x2F;2020&#x2F;avif-has-landed&#x2F;&quot;&gt;AVIF has landed&lt;&#x2F;a&gt; by Jake Archibald — Compares image sizes and qualities of different formats: SVG, JPEG, PNG, WebP, and AVIF.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;avif.io&#x2F;&quot;&gt;avif.io&lt;&#x2F;a&gt; — Fast, configurable, client-side image compression that works on desktop and mobile.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;squoosh.app&#x2F;&quot;&gt;Squoosh&lt;&#x2F;a&gt; — another image compression service built with WebAssembly that supports AVIF&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.cloudflare.com&#x2F;workers&#x2F;examples&quot;&gt;Tons of great examples on how to configure Cloudflare workers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;workers.cloudflare.com&#x2F;sites&quot;&gt;Cloudflare Workers Sites&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Launching a Side Project Backed by Github Sponsors</title>
        <published>2020-08-21T00:00:00+00:00</published>
        <updated>2020-08-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2020/sponsors/"/>
        <id>https://endler.dev/2020/sponsors/</id>
        
        <content type="html" xml:base="https://endler.dev/2020/sponsors/">&lt;p&gt;Yesterday we launched &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;analysis-tools.dev&quot;&gt;analysis-tools.dev&lt;&#x2F;a&gt;, and boy had I underestimated the response.&lt;&#x2F;p&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;analysis-tools.dev&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;website.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;website.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;983&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;It’s a side project about comparing static code analysis tools.
Static analysis helps improve code quality by detecting bugs in source code
without even running it.&lt;&#x2F;p&gt;
&lt;p&gt;What’s best about the project is that it’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;analysis-tools-dev&#x2F;&quot;&gt;completely open-source&lt;&#x2F;a&gt;. We wanted to
build a product that wouldn’t depend on showing ads or tracking users. Instead,
we were asking for sponsors on Github — that’s it. We learned a lot in the
process, and if you like to do the same, keep reading!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;first-some-stats&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#first-some-stats&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;First, Some Stats&lt;&#x2F;h2&gt;
&lt;p&gt;Everyone likes business metrics. Here are some of ours:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The project started as an &lt;em&gt;awesome list&lt;&#x2F;em&gt; on Github in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;obsolete&#x2F;&quot;&gt;December
2015&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;We’re currently listing 470 static analysis tools.&lt;&#x2F;li&gt;
&lt;li&gt;Traffic grew continuously. Counting 7.5k stars and over 190 contributors at
the moment.&lt;&#x2F;li&gt;
&lt;li&gt;500-1000 unique users per week.&lt;&#x2F;li&gt;
&lt;li&gt;I had the idea to build a website for years now, but my coworker &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jakubsacha&quot;&gt;Jakub&lt;&#x2F;a&gt;
joined in May 2020 to finally make it a reality.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;star-history.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;star-history.jpg&quot; 
        
            alt=&quot;Github stars over time. That graph screams BUSINESS OPPORTUNITY.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;424&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Github stars over time. That graph screams BUSINESS OPPORTUNITY.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;star-history.t9t.io&quot;&gt;star-history.t9t.io&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;“Why did it take five years to build a website!?”, I hear you ask. Because I
thought the idea was so obvious that others must have tried before and failed.&lt;&#x2F;p&gt;
&lt;p&gt;I put it off, even though nobody stepped in to fill this niche.&lt;br &#x2F;&gt;
I put it off, even though I kept the list up-to-date for five years, just to
learn about the tools out there.&lt;br &#x2F;&gt;
You get the gist: don’t put things off for too long. When ideas sound obvious, it’s probably because they are.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;revenue-model&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#revenue-model&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Revenue Model&lt;&#x2F;h2&gt;
&lt;p&gt;It took a while to figure out how to support the project financially. We knew
what we didn’t want: an SEO landfill backed by AdWords. Neither did we want to
“sell user data” to trackers.&lt;&#x2F;p&gt;
&lt;p&gt;We owe it to the contributors on Github to keep all data free for everyone.
How could we still build a service around it?
Initially, we thought about swallowing the infrastructure costs
ourselves, but we’d have no incentive to maintain the site or extend it with new
features.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sponsors&quot;&gt;Github Sponsors&lt;&#x2F;a&gt; was still quite new at that time. Yet, as soon as we realized
that it was an option, it suddenly clicked: Companies that are not afraid of a
comparison with the competition have an incentive to support an open platform
that facilitates that. Furthermore, we could avoid bias and
build a product that makes comparing objective and accessible.&lt;&#x2F;p&gt;
&lt;p&gt;Sponsoring could be the antidote to soulless growth and instead allow us to build
a lean, sustainable side business. We don’t expect analysis-tools.dev ever to be
a full-time job. The market might be too small for that — and that’s fine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tech&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#tech&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Tech&lt;&#x2F;h2&gt;
&lt;p&gt;Once we had a revenue model, we could focus on the tech. We’re both engineers,
which helps with iterating quickly.&lt;&#x2F;p&gt;
&lt;p&gt;Initially, I wanted to build something fancy with
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yewstack&#x2F;yew&quot;&gt;Yew&lt;&#x2F;a&gt;. It’s a Rust&#x2F;Webassembly framework and
your boy &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2019&#x2F;tinysearch&#x2F;&quot;&gt;likes Rust&#x2F;Webassembly&lt;&#x2F;a&gt;…&lt;&#x2F;p&gt;
&lt;p&gt;I’m glad Jakub suggested something else: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gatsbyjs.com&#x2F;&quot;&gt;Gatsby&lt;&#x2F;a&gt;. Now, let me be honest with
you: I couldn’t care less about Gatsby. And that’s what I said to Jakub: “I
couldn’t care less about Gatsby.” But that’s precisely the point: not being
emotionally attached to something makes us focus on the job and not the tool.
We get more stuff done!&lt;&#x2F;p&gt;
&lt;p&gt;From there on, it was pretty much easy going: we used a starter template, Jakub
showed me how the GraphQL integration worked, and we
even got to use some Rust! The site runs on Cloudflare as an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;workers.cloudflare.com&#x2F;&quot;&gt;edge
worker&lt;&#x2F;a&gt; built on top of Rust. (Yeah, I cheated
a bit.)&lt;&#x2F;p&gt;
&lt;p&gt;Count to three, MVP!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finding-sponsors&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#finding-sponsors&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Finding Sponsors&lt;&#x2F;h2&gt;
&lt;p&gt;So we had our prototype but zero sponsors so far. What started now was (and
still is) by far the hardest part: convincing people to support us.&lt;&#x2F;p&gt;
&lt;p&gt;We were smart enough not to send cold e-mails because most companies ignore
them. Instead, we turned to our network and realized that developers reached out
before to add their company’s projects to the old static analysis list on
Github.&lt;&#x2F;p&gt;
&lt;p&gt;These were the people we contacted first. We tried to keep the messages short
and personal.&lt;&#x2F;p&gt;
&lt;p&gt;What worked best was a medium-sized e-mail with some context and a reminder that
they contributed to the project before. We included a link to our &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sponsors&#x2F;analysis-tools-dev&#x2F;&quot;&gt;sponsors
page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Businesses want reliable partners and a reasonable value proposal,
so a prerequisite is that the sponsor page has to be meticulously polished.&lt;&#x2F;p&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;sponsors&amp;#x2F;analysis-tools-dev&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;sponsors.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;sponsors.jpg&quot; 
        
            alt=&quot;Our Github Sponsors page&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;1179&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
        &lt;figcaption&gt;
            
            Our Github Sponsors page
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Just like &lt;em&gt;Star Wars Episode IX&lt;&#x2F;em&gt;, we received mixed reviews: many people never
replied, others passed the message
on to their managers, which in turn never replied, while others again had no
interest in sponsoring open-source projects in general. That’s all fair game:
people are busy, and sponsorware is quite a new concept.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A little rant: I’m of the opinion that tech businesses don’t nearly sponsor
enough compared to all the value they get from Open Source. Would your company
exist if there hadn’t been a free operating system like Linux or a web server
like Nginx or Apache when it was founded?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;There was, however, a rare breed of respondents, which expressed interest but
needed some guidance. For many, it is the first step towards sponsoring &lt;em&gt;any&lt;&#x2F;em&gt;
developer through Github Sponsors &#x2F; OpenCollective.&lt;&#x2F;p&gt;
&lt;p&gt;It helped that we use OpenCollective as our fiscal host, which handles invoicing
and donation transfers. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.opencollective.com&#x2F;help&#x2F;&quot;&gt;Their docs&lt;&#x2F;a&gt;
helped us a lot when getting started.&lt;&#x2F;p&gt;
&lt;p&gt;The task of finding sponsors &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=LT_y5qri00o&quot;&gt;is never
done&lt;&#x2F;a&gt;, but it was very reassuring
to hear from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.deepcode.ai&#x2F;&quot;&gt;DeepCode&lt;&#x2F;a&gt; - an AI-based semantic
analysis service, that they were willing to take a chance on us.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to them, we could push product over the finishing line. Because of them,
we can keep the site free for everybody. It also means the website is kept free
from ads and trackers.&lt;&#x2F;p&gt;
&lt;p&gt;In turn, DeepCode gets exposed to many great developers that care about code
quality and might become loyal customers. Also, they get recognized as an
open-source-friendly tech company, which is more important than ever if you’re
trying to sell dev tools. Win-win!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;marketing&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#marketing&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Marketing&lt;&#x2F;h2&gt;
&lt;p&gt;Jakub and I both had started businesses before, but this was the first truly
&lt;em&gt;open&lt;&#x2F;em&gt; product we would build.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Phase 1: Ship early 🚀&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We decided for a soft launch: deploy the site as early as possible and let the
crawlers index it. The fact that the page is statically rendered and follows
some basic SEO guidelines sure helped with improving our search engine rankings
over time.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Phase 2: Ask for feedback from your target audience 💬&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;After we got some organic traffic and our first votes, we reached out to our
developer friends to test the page and vote on tools they know and love. This
served as an early validation, and we got some honest feedback, which helped us
catch the most blatant flaws.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Phase 3: Prepare announcement post 📝&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;We wrote a blog post which, even if clickbaity, got the job done: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;analysis-tools.dev&#x2F;blog&#x2F;static-analysis-is-broken-lets-fix-it&quot;&gt;Static
Analysis is Broken — Let’s Fix
It!&lt;&#x2F;a&gt; It
pretty much captures our frustration about the space and why building an open
platform is important. We could have done a better job explaining the technical
differences between the different analysis tools, but that’s for another day.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Phase 4: Announce on social media 🔥&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Shortly before the official announcement, we noticed that the search
functionality was broken (of course). Turns out, we hit the free quota limit on
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;algolia.com&quot;&gt;Algolia&lt;&#x2F;a&gt; a biiit earlier than expected. 😅 No biggie: quick
exchange with Algolia’s customer support, and they moved us over to the
open-source plan (which we didn’t know existed). We were back on track!&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Site note: Algolia customer support is top-notch. Responsive, tech-savvy,
and helpful. Using Algolia turned out to be a great fit for our product.
Response times are consistently in the low milliseconds and the integration
with Gatsby was quick and easy.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;twitter.com&amp;#x2F;matthiasendler&amp;#x2F;status&amp;#x2F;1296162427797671936&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;tweet.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;tweet.jpg&quot; 
        
            alt=&quot;We got quite a bit of buzz from that
tweet: 63 retweets, 86 likes and counting&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;230&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
        &lt;figcaption&gt;
            
            We got quite a bit of buzz from that
tweet: 63 retweets, 86 likes and counting
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Clearly, everyone knew that we were asking for support here, but we are thankful
for every single one that liked and retweeted. It’s one of these situations
where having a network of like-minded people can help.&lt;&#x2F;p&gt;
&lt;p&gt;As soon as we were confident that the site wasn’t &lt;em&gt;completely&lt;&#x2F;em&gt; broken, we set off
to announce it on
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lobste.rs&#x2F;s&#x2F;n2ecfs&#x2F;static_analysis_is_broken_let_s_fix_it&quot;&gt;Lobste.rs&lt;&#x2F;a&gt;
(2 downvotes),
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;SideProject&#x2F;comments&#x2F;icupeu&#x2F;we_made_a_website_to_compare_470_static_analysis&#x2F;&quot;&gt;&#x2F;r&#x2F;SideProject&lt;&#x2F;a&gt;
(3 upvotes) and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=24221708&quot;&gt;Hacker News&lt;&#x2F;a&gt; (173
upvotes, 57 comments). Social media is kind of unpredictable.
It helps to cater the message to each audience and stay humble, though.&lt;&#x2F;p&gt;
&lt;p&gt;The response from all of that marketing effort was &lt;strong&gt;nuts&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;traffic.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;traffic.jpg&quot; 
        
            alt=&quot;Traffic on launch day&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;298&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Traffic on launch day
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Perhaps unsurprisingly, the Cloudflare edge workers didn’t break a sweat.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;worker.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;worker.jpg&quot; 
        
            alt=&quot;Edge worker CPU time on Cloudflare&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;353&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Edge worker CPU time on Cloudflare
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;My boss &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;xo4n&quot;&gt;Xoan Vilas&lt;&#x2F;a&gt; even did a quick performance
analysis and he approved. (Thanks boss!)&lt;&#x2F;p&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;twitter.com&amp;#x2F;xo4n&amp;#x2F;status&amp;#x2F;1296432035788193794&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;perf.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;perf.jpg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;489&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;High fives all around!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;now-what&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#now-what&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Now what?&lt;&#x2F;h2&gt;
&lt;p&gt;Of course, we’ll add new features; of course, we have more plans for the future,
yada yada yada. Instead, let’s reflect on that milestone: a healthy little
business with no ads or trackers, solely carried by sponsors. 🎉&lt;&#x2F;p&gt;
&lt;p&gt;Finally, I want you to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9XGyxOwM0tE&quot;&gt;look deep inside yourself and find your own little
product to work on&lt;&#x2F;a&gt;. It’s probably
right in front of your nose, and like myself, you’ve been putting it off for too
long. Well, not anymore! The next success story is yours. So go out and build
things.&lt;&#x2F;p&gt;
&lt;p&gt;Oh wait! …before you leave, would you mind checking out
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;analysis-tools.dev&#x2F;&quot;&gt;analysis-tools.dev&lt;&#x2F;a&gt; and smashing that upvote button
for a few tools you like? Hey, and if you feel super generous today
(or you have a fabulous employer that cares about open-source), why not check out
our &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sponsors&#x2F;analysis-tools-dev&#x2F;&quot;&gt;sponsorship page&lt;&#x2F;a&gt;?&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;team.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;sponsors&amp;#x2F;team.jpg&quot; 
        
            alt=&quot;Jakub and me in Vienna, Austria. I&amp;#x27;m not actually that small.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;488&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Jakub and me in Vienna, Austria. I’m not actually that small.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What Happened To Programming In The 2010s?</title>
        <published>2020-07-02T00:00:00+00:00</published>
        <updated>2021-10-11T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2020/review/"/>
        <id>https://endler.dev/2020/review/</id>
        
        <content type="html" xml:base="https://endler.dev/2020/review/">&lt;p&gt;A while ago, I read an article titled &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;avc.com&#x2F;2019&#x2F;12&#x2F;what-happened-in-the-2010s&#x2F;&quot;&gt;“What Happened In The
2010s”&lt;&#x2F;a&gt; by Fred Wilson. The
post highlights key changes in technology and business during the last ten
years. This inspired me to think about a much more narrow topic: &lt;em&gt;What Happened To
Programming In The 2010s?&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;🚓 I probably forgot like 90% of what actually happened. Please
don’t sue me.
My goal is to reflect on the &lt;u&gt;past&lt;&#x2F;u&gt; so that you can better predict the &lt;u&gt;future&lt;&#x2F;u&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;h2 id=&quot;where-to-start&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#where-to-start&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Where To Start?&lt;&#x2F;h2&gt;
&lt;p&gt;From a mile-high perspective, programming is still the same as a decade ago:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Punch program into editor&lt;&#x2F;li&gt;
&lt;li&gt;Feed to compiler (or interpreter)&lt;&#x2F;li&gt;
&lt;li&gt;Bleep Boop 🤖&lt;&#x2F;li&gt;
&lt;li&gt;Receive output&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;But if we take a closer look, a &lt;em&gt;lot&lt;&#x2F;em&gt; has changed around us.
Many things we take for granted today didn’t exist a decade ago.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-happened-before&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-happened-before&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;What Happened Before?&lt;&#x2F;h2&gt;
&lt;p&gt;Back in 2009, we wrote &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jquery.com&#x2F;&quot;&gt;jQuery&lt;&#x2F;a&gt; plugins, ran websites on
shared hosting services, and uploaded content via
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;File_Transfer_Protocol&quot;&gt;FTP&lt;&#x2F;a&gt;. Sometimes code was
copy-pasted from dubious forums, tutorials on blogs, or even hand-transcribed
from books. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;&quot;&gt;Stack Overflow&lt;&#x2F;a&gt; (which launched on
15&lt;sup&gt;th&lt;&#x2F;sup&gt; of September 2008) was still in its infancy. Version control
was done with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Concurrent_Versions_System&quot;&gt;CVS&lt;&#x2F;a&gt; or
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Apache_Subversion&quot;&gt;SVN&lt;&#x2F;a&gt; — or not at all.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2018&#x2F;github&#x2F;&quot;&gt;I signed up for Github&lt;&#x2F;a&gt; on 3&lt;sup&gt;rd&lt;&#x2F;sup&gt; of
January 2010. Nobody had even heard of a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Raspberry_Pi&quot;&gt;Raspberry
Pi&lt;&#x2F;a&gt; (which only got released in
2012).&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;review&amp;#x2F;xkcd_2324.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;review&amp;#x2F;xkcd_2324.jpg&quot; 
        
            alt=&quot;&amp;lt;a href=&amp;#x27;https:&amp;#x2F;&amp;#x2F;xkcd.com&amp;#x2F;2324&amp;#x2F;&amp;#x27;&amp;gt;xkcd #2324&amp;lt;&amp;#x2F;a&amp;gt;&quot;
        

        

        
        
        
            width=&quot;640&quot;
        
        
            height=&quot;572&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: &lt;a href=&#x27;https:&#x2F;&#x2F;xkcd.com&#x2F;2324&#x2F;&#x27;&gt;xkcd #2324&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;an-explosion-of-new-programming-languages&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#an-explosion-of-new-programming-languages&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;An Explosion Of New Programming Languages&lt;&#x2F;h2&gt;
&lt;p&gt;The last decade saw the creation of a vast number of new and exciting programming
languages.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crystal-lang.org&#x2F;&quot;&gt;Crystal&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dart.dev&#x2F;&quot;&gt;Dart&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;elixir-lang.org&#x2F;&quot;&gt;Elixir&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;elm-lang.org&#x2F;&quot;&gt;Elm&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;golang.org&#x2F;&quot;&gt;Go&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;julialang.org&#x2F;&quot;&gt;Julia&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kotlinlang.org&#x2F;&quot;&gt;Kotlin&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nim-lang.org&#x2F;&quot;&gt;Nim&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;Rust&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;swift.org&#x2F;&quot;&gt;Swift&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.typescriptlang.org&#x2F;&quot;&gt;TypeScript&lt;&#x2F;a&gt;
all released their first stable version!&lt;&#x2F;p&gt;
&lt;p&gt;Even more exciting: &lt;em&gt;all&lt;&#x2F;em&gt; of the above languages are developed in the open now, and the source code is
freely available on Github. That means, everyone can contribute to their development — a big testament to Open Source.&lt;&#x2F;p&gt;
&lt;p&gt;Each of those languages introduced new ideas that were not widespread before:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Strong Type Systems&lt;&#x2F;em&gt;: Kotlin and Swift made &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Nullable_type&quot;&gt;optional null types&lt;&#x2F;a&gt;
mainstream, TypeScript brought types to JavaScript, Algebraic datatypes are
common in Kotlin, Swift, TypeScript, and Rust.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Interoperability&lt;&#x2F;em&gt;: Dart compiles to JavaScript, Elixir interfaces with
Erlang, Kotlin with Java, and Swift with Objective-C.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;em&gt;Better Performance&lt;&#x2F;em&gt;: Go promoted Goroutines and channels for easier
concurrency and impressed with a
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.golang.org&#x2F;ismmkeynote&quot;&gt;sub-millisecond&lt;&#x2F;a&gt; Garbage Collector,
while Rust avoids Garbage Collector overhead altogether thanks to ownership and borrowing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is just a short list, but innovation in the programming language field has
greatly accelerated.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-innovation-in-older-languages&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#more-innovation-in-older-languages&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;More Innovation in Older Languages&lt;&#x2F;h2&gt;
&lt;p&gt;Established languages didn’t stand still either. A few examples:&lt;&#x2F;p&gt;
&lt;p&gt;C++ woke up from its long winter sleep and released C++11 after its last major
release in 1998. It introduced numerous new features like Lambdas, &lt;code&gt;auto&lt;&#x2F;code&gt;
pointers, and range-based loops to the language.&lt;&#x2F;p&gt;
&lt;p&gt;At the beginning of the last decade, the latest PHP version was 5.3. We’re at
7.4 now. (We skipped 6.0, but I’m not ready to talk about it yet.) Along the
way, it got over twice as fast. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stephencoakley.com&#x2F;2020&#x2F;06&#x2F;10&#x2F;dumb-reasons-to-hate-php&quot;&gt;PHP is a truly modern programming language
now&lt;&#x2F;a&gt; with a
thriving ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;Heck, even Visual Basic has tuples now. (Sorry, I couldn’t resist.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;faster-release-cycles&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#faster-release-cycles&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Faster Release Cycles&lt;&#x2F;h2&gt;
&lt;p&gt;Most languages adopted a quicker release cycle. Here’s a list for some popular languages:&lt;&#x2F;p&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Language&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: left&quot;&gt;Current release cycle&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;C&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;irregular&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;C#&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;~ 12 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;C++&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;~ 3 years&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Go&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;6 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Java&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;6 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;JavaScript (ECMAScript)&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;12 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;PHP&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;12 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Python&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;12 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Ruby&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;12 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Rust&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;6 weeks (!)&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Swift&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;6 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;Visual Basic .NET&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: left&quot;&gt;~ 24 months&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h2 id=&quot;the-slow-death-of-null&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-slow-death-of-null&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Slow Death Of Null&lt;&#x2F;h2&gt;
&lt;p&gt;Close to the end of the last decade, in a talk from 25&lt;sup&gt;th&lt;&#x2F;sup&gt;of August 2009,
Tony Hoare described the &lt;code&gt;null&lt;&#x2F;code&gt; pointer as his &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.infoq.com&#x2F;presentations&#x2F;Null-References-The-Billion-Dollar-Mistake-Tony-Hoare&#x2F;&quot;&gt;Billion Dollar
Mistake&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A study by the Chromium project found that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.chromium.org&#x2F;Home&#x2F;chromium-security&#x2F;memory-safety&quot;&gt;70% of their serious security bugs were memory safety problems&lt;&#x2F;a&gt; (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.zdnet.com&#x2F;article&#x2F;microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues&#x2F;&quot;&gt;same for Microsoft&lt;&#x2F;a&gt;). Fortunately, the notion that our &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;@sgrif&#x2F;no-the-problem-isnt-bad-coders-ed4347810270&quot;&gt;memory safety problem isn’t bad coders&lt;&#x2F;a&gt;
has finally gained some traction.&lt;br &#x2F;&gt;
Many mainstream languages embraced safer alternatives to &lt;code&gt;null&lt;&#x2F;code&gt;: nullable
types, &lt;code&gt;Option&lt;&#x2F;code&gt;, and &lt;code&gt;Result&lt;&#x2F;code&gt; types. Languages like Haskell had these features
before, but they only gained popularity in the 2010s.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;revenge-of-the-type-system&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#revenge-of-the-type-system&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Revenge of the Type System&lt;&#x2F;h2&gt;
&lt;p&gt;Closely related is the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.johndcook.com&#x2F;blog&#x2F;2010&#x2F;06&#x2F;09&#x2F;dynamic-typing-and-risk-homeostasis&#x2F;&quot;&gt;debate about type
systems&lt;&#x2F;a&gt;.
The past decade has seen type systems make their stage comeback; TypeScript,
Python, and PHP (just to name a few) started to embrace type systems.&lt;&#x2F;p&gt;
&lt;p&gt;The trend goes towards type inference: add types to make your intent clearer for
other humans and in the face of ambiguity — otherwise, skip them. Java,
C++, Go, Kotlin, Swift, and Rust are popular examples with type inference support. I
can only speak for myself, but I think writing Java has become a lot more
ergonomic in the last few years.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;exponential-growth-of-libraries-and-frameworks&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#exponential-growth-of-libraries-and-frameworks&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Exponential Growth Of Libraries and Frameworks&lt;&#x2F;h2&gt;
&lt;p&gt;As of today, npm hosts &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.npmjs.com&#x2F;&quot;&gt;1,330,634 packages&lt;&#x2F;a&gt;. That’s over a million
packages that somebody else is maintaining for you. Add another &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rubygems.org&#x2F;stats&quot;&gt;160,488 Ruby
gems&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;pypi.org&#x2F;&quot;&gt;243,984 Python projects&lt;&#x2F;a&gt;,
and top it off with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;&quot;&gt;42,547 Rust crates&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;review&amp;#x2F;module_counts.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;review&amp;#x2F;module_counts.jpg&quot; 
        
            alt=&quot;Number of packages for popular programming languages.&amp;lt;br &amp;#x2F;&amp;gt; Don&amp;#x27;t ask me what happened to npm in 2019.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;494&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Number of packages for popular programming languages.&lt;br &#x2F;&gt; Don’t ask me what happened to npm in 2019.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a href=&#x27;http:&#x2F;&#x2F;www.modulecounts.com&#x2F;&#x27;&gt;Module Counts&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Of course, there’s the occasional
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.davidhaney.io&#x2F;npm-left-pad-have-we-forgotten-how-to-program&#x2F;&quot;&gt;leftpad&lt;&#x2F;a&gt;,
but it also means that we have to write less library code ourselves and can
focus on business value instead. On the other hand, there are more potential
points of failure, and auditing is difficult. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sambleckley.com&#x2F;writing&#x2F;npm.html&quot;&gt;There is also a large number of outdated
packages&lt;&#x2F;a&gt;. For a more in-depth discussion, I recommend the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.coreinfrastructure.org&#x2F;wp-content&#x2F;uploads&#x2F;sites&#x2F;6&#x2F;2020&#x2F;02&#x2F;census_ii_vulnerabilities_in_the_core.pdf&quot;&gt;Census II report by
the Linux Foundation &amp;amp; Harvard&lt;&#x2F;a&gt; [PDF].&lt;&#x2F;p&gt;
&lt;p&gt;We also went a bit crazy on frontend frameworks:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;angularjs.org&#x2F;&quot;&gt;Angular&lt;&#x2F;a&gt; in 2010&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;reactjs.org&#x2F;&quot;&gt;React&lt;&#x2F;a&gt; in 2013&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vuejs.org&#x2F;&quot;&gt;Vue&lt;&#x2F;a&gt; in 2014&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;svelte.dev&#x2F;&quot;&gt;Svelte&lt;&#x2F;a&gt; in 2016&lt;&#x2F;li&gt;
&lt;li&gt;…and soon &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;yewstack&#x2F;yew&#x2F;&quot;&gt;Yew&lt;&#x2F;a&gt;?&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;no-free-lunch&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#no-free-lunch&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;No Free Lunch&lt;&#x2F;h2&gt;
&lt;p&gt;A review like this wouldn’t be complete without taking a peek at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Moore&amp;#x27;s_law&quot;&gt;Moore’s Law&lt;&#x2F;a&gt;.
It has held up surprisingly well in the last decade:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;review&amp;#x2F;moore_2018.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;review&amp;#x2F;moore_2018.jpg&quot; 
        
            alt=&quot;&amp;lt;a href=&amp;#x27;https:&amp;#x2F;&amp;#x2F;en.wikipedia.org&amp;#x2F;wiki&amp;#x2F;Moore%27s_law&amp;#x27;&amp;gt;Wikipedia&amp;lt;&amp;#x2F;a&amp;gt;&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;469&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: &lt;a href=&#x27;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Moore%27s_law&#x27;&gt;Wikipedia&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;There’s a catch, though.
Looking at single-core performance, the curve is flattening:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;review&amp;#x2F;moore_single.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;review&amp;#x2F;moore_single.jpg&quot; 
        
            alt=&quot;&amp;lt;a href=&amp;#x27;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;watch?v=Azt8Nc-mtKM&amp;amp;&amp;#x27;&amp;gt;Standford University: The Future of Computing (video)&amp;lt;&amp;#x2F;a&amp;gt;&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;347&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: &lt;a href=&#x27;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Azt8Nc-mtKM&amp;&#x27;&gt;Standford University: The Future of Computing (video)&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The new transistors prophesied by Moore don’t make our CPUs faster but instead
add other kinds of processing capabilities like more parallelism or hardware
encryption.
There is no free lunch anymore. Engineers have to find new ways of making their
applications faster, e.g. by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Concurrent_computing&quot;&gt;embracing concurrent
execution&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Callbacks, coroutines, and eventually async&#x2F;await are becoming industry
standards.&lt;&#x2F;p&gt;
&lt;p&gt;GPUs (Graphical Processing Units) became very powerful, allowing for massively
parallel computations, which caused a renaissance of Machine Learning for practical use-cases:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Deep learning becomes feasible, which leads to machine learning becoming
integral to many widely used software services and applications.
— &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Timeline_of_machine_learning&quot;&gt;Timeline of Machine Learning on Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;&lt;em&gt;Compute&lt;&#x2F;em&gt; is ubiquitous, so in most cases, energy efficiency plays a more prominent role now than raw performance (at least for consumer devices).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unlikely-twists-of-fate&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#unlikely-twists-of-fate&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Unlikely Twists Of Fate&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Microsoft is a cool kid now. It acquired Github, announced the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Windows_Subsystem_for_Linux&quot;&gt;Windows subsystem for Linux&lt;&#x2F;a&gt; (which should really be called Linux Subsystem for Windows), open sourced
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Microsoft&#x2F;MS-DOS&quot;&gt;MS-DOS&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;news.microsoft.com&#x2F;2014&#x2F;11&#x2F;12&#x2F;microsoft-takes-net-open-source-and-cross-platform-adds-new-development-capabilities-with-visual-studio-2015-net-2015-and-visual-studio-online&#x2F;&quot;&gt;.NET&lt;&#x2F;a&gt;.
Even the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Microsoft&#x2F;calculator&quot;&gt;Microsoft Calculator&lt;&#x2F;a&gt; is now open source.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.redhat.com&#x2F;en&#x2F;blog&#x2F;red-hat-ibm-creating-leading-hybrid-cloud-provider&quot;&gt;IBM acquired Red Hat&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lore.kernel.org&#x2F;lkml&#x2F;CA+55aFy+Hv9O5citAawS+mVZO+ywCKd9NQ2wxUmGsz9ZJzqgJQ@mail.gmail.com&#x2F;&quot;&gt;Linus Torvalds apologized for his behavior, took time off&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Open source became the default for software development (?).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;learnings&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#learnings&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Learnings&lt;&#x2F;h2&gt;
&lt;p&gt;If you’re now thinking: &lt;em&gt;Matthias, you totally forgot X&lt;&#x2F;em&gt;, then I brought
that point home. This is not even close to everything that happened. You’d
roughly need a decade to talk about all of it.&lt;&#x2F;p&gt;
&lt;p&gt;Personally, I’m excited about the &lt;em&gt;next&lt;&#x2F;em&gt; ten years.
Software is eating the world — at an ever-faster pace.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Tips for Faster Rust Compile Times</title>
        <published>2020-06-21T00:00:00+00:00</published>
        <updated>2023-06-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2020/rust-compile-times/"/>
        <id>https://endler.dev/2020/rust-compile-times/</id>
        
        <content type="html" xml:base="https://endler.dev/2020/rust-compile-times/">&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;This post has &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;corrode.dev&#x2F;blog&#x2F;tips-for-faster-rust-compile-times&#x2F;&quot;&gt;moved to my other blog&lt;&#x2F;a&gt;.
It will be updated there in the future.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Gravity</title>
        <published>2020-05-29T00:00:00+00:00</published>
        <updated>2020-05-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2020/gravity/"/>
        <id>https://endler.dev/2020/gravity/</id>
        
        <content type="html" xml:base="https://endler.dev/2020/gravity/">&lt;p&gt;Here’s a test to show your age:&lt;&#x2F;p&gt;
&lt;p&gt;Do you still remember &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;josephpcohen.com&#x2F;w&#x2F;gravityscript&#x2F;&quot;&gt;that funny JavaScript gravity effect&lt;&#x2F;a&gt;, which Google used on their homepage ten years ago? This one?&lt;&#x2F;p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;wskgClFNlJw&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;gravity.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;gravity.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;p&gt;I wanted to have some fun and integrated it into a website I was building.
Unfortunately, it didn’t work out-of-the-box.
It choked on some DOM elements that were not strictly classes (like SVG elements).
So, in good hacker fashion, I quickly patched up the script (it’s just a three-line change), and now it’s back to its former glory.&lt;&#x2F;p&gt;
&lt;p&gt;Test it here! (Caution: you’ll have to reload the page after that. 😏)&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a class=&quot;btn&quot; href=&#x27;#&#x27; id=&#x27;gravity&#x27;&gt;Apply Gravity&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;script defer type=&quot;text&#x2F;javascript&quot;&gt;
    var myLink = document.getElementById(&#x27;gravity&#x27;);

    myLink.onclick = function(){

        var script = document.createElement(&quot;script&quot;);
        script.type = &quot;text&#x2F;javascript&quot;;
        script.src = &quot;gravity.js&quot;; 
        document.getElementsByTagName(&quot;head&quot;)[0].appendChild(script);
        return false;
    }
&lt;&#x2F;script&gt;
&lt;p&gt;Anyway, feel free to add it to your own sites and have some fun.
It’s also great to prank your friends.
Simply add that single line to any website and weeee!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt;  type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;text&#x2F;javascript&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt;  src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-meta z-embedded&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;endler.dev&#x2F;2020&#x2F;gravity&#x2F;gravity.js&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Sometimes I miss those simple times of the early web…&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Hacker Folklore</title>
        <published>2020-04-24T00:00:00+00:00</published>
        <updated>2025-02-03T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2020/folklore/"/>
        <id>https://endler.dev/2020/folklore/</id>
        
        <content type="html" xml:base="https://endler.dev/2020/folklore/">&lt;p&gt;Some computer terms have a surprising legacy. Many of them are derived from
long-obsolete technologies. This post tries to dust off the exciting history of
some
of these terms that we use every day but aren’t quite sure about their origins.
Let’s jump right in!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bike-shedding&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bike-shedding&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Bike-Shedding&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A pointless discussion about trivial issues.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The term bike-shed effect or bike-shedding was coined as a metaphor to
illuminate the law of triviality; it was popularised in the Berkeley Software
Distribution community by the Danish computer developer &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;phk.freebsd.dk&#x2F;sagas&#x2F;bikeshed&#x2F;&quot;&gt;Poul-Henning Kamp in
1999 on the FreeBSD mailing list&lt;&#x2F;a&gt; and has
spread from there to the whole software industry.&lt;&#x2F;p&gt;
&lt;p&gt;The concept was first presented as a corollary of his broader “Parkinson’s law”
spoof of management. He dramatizes this “law of triviality” with the example of
a committee’s deliberations on an atomic reactor, contrasting it to
deliberations on a bicycle shed. As he put it: “The time spent on any item of
the agenda will be in inverse proportion to the sum of money involved.”&lt;&#x2F;p&gt;
&lt;p&gt;A reactor is so vastly expensive and complicated that an average person cannot
understand it, so one assumes that those who work on it understand it. On the
other hand, everyone can visualize a cheap, simple bicycle shed, so planning one
can result in endless discussions because everyone involved wants to add a touch
and show personal contribution.&lt;br &#x2F;&gt;
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Law_of_triviality&quot;&gt;Reference - Wikipedia: Law of Triviality&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;boilerplate&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#boilerplate&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Boilerplate&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;bending-roll.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;bending-roll.jpg&quot; 
        
            alt=&quot;An old machine that bended steel
plates to water boilers.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;386&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            An old machine that bended steel
plates to water boilers.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Modern_mechanism,_exhibiting_the_latest_progress_in_machines,_motors,_and_the_transmission_of_power,_being_a_supplementary_volume_to_Appletons&amp;#x27;_cyclopaedia_of_applied_mechanics_(1892)_(14583761620).jpg&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A chunk of code that is copied over and over again with little
or no changes made to it in the process.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Boiler plate&lt;&#x2F;em&gt; originally referred to the rolled steel used to make water
boilers but is used in the media to refer to hackneyed or unoriginal writing.
The term refers to the metal printing plates of pre-prepared text such as
advertisements or syndicated columns that were distributed to small, local
newspapers. These printing plates came to be known as ‘boilerplates’ by analogy.
One large supplier to newspapers of this kind of boilerplate was the Western
Newspaper Union, which supplied “ready-to-print stories [which] contained
national or international news” to papers with smaller geographic footprints,
which could include advertisements pre-printed next to the conventional content.&lt;&#x2F;p&gt;
&lt;p&gt;References:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Boilerplate_text&quot;&gt;Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;3997441&#x2F;270334&quot;&gt;Stack Overflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;english.stackexchange.com&#x2F;questions&#x2F;464924&#x2F;boilerplate-versus-template&#x2F;464929&quot;&gt;StackExchange - English Language &amp;amp;
Usage&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;boilerplate.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;boilerplate.jpg&quot; 
        
            alt=&quot;The man in the foreground is holding
a rounded printing plate. Plates like this were provided by companies such as
Western Newspaper Union to many smaller newspapers.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;506&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            The man in the foreground is holding
a rounded printing plate. Plates like this were provided by companies such as
Western Newspaper Union to many smaller newspapers.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;english.stackexchange.com&#x2F;a&#x2F;464929&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;boot-reboot-bootstrapping&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#boot-reboot-bootstrapping&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Boot &#x2F; Reboot &#x2F; Bootstrapping&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;muenchhausen.svg&quot; 
        
            alt=&quot;Lithography of Baron M&amp;amp;uuml;nchhausen
pulling himself out of a swamp by his pigtail&quot;
        

        

        
        
        
            width=&quot;2050&quot;
        
        
            height=&quot;2351&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            Lithography of Baron Münchhausen
pulling himself out of a swamp by his pigtail
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Zentralbibliothek_Solothurn_-_M%C3%BCnchhausen_zieht_sich_am_Zopf_aus_dem_Sumpf_-_a0400.tif#filelinks&quot;&gt;Wikimedia&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The term &lt;em&gt;boot&lt;&#x2F;em&gt; is used in the context of computers to refer to the process of
starting a computer.&lt;&#x2F;p&gt;
&lt;p&gt;In compiler development, the term &lt;em&gt;bootstrapping&lt;&#x2F;em&gt; refers to the process of
rewriting a compiler in a new language: The first compiler is written in an
existing language. Then it gets rewritten in the new language and compiled by
itself.&lt;&#x2F;p&gt;
&lt;p&gt;The saying “to pull oneself up by one’s bootstraps” dates back to the 19th
century. Tall boots may have a tab, loop or handle at the top allowing one to
help pulling them on. The metaphor spawned additional metaphors for
self-sustaining processes that proceed without external help.&lt;&#x2F;p&gt;
&lt;p&gt;According to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Bootstrapping_(computing)&quot;&gt;Wikipedia&lt;&#x2F;a&gt;,&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The idiom dates at least to 1834, when it appeared in the Workingman’s
Advocate: “It is conjectured that Mr. Murphee will now be enabled to hand
himself over the Cumberland river or a barn yard fence by the straps of his
boots.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;There’s also a nice summary in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.merriam-webster.com&#x2F;words-at-play&#x2F;reboot-boot-word-origin&quot;&gt;Merriam-Webster&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bug&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bug&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Bug&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A defect in a piece of code or hardware.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The origins are unknown!&lt;&#x2F;p&gt;
&lt;p&gt;Contrary to popular belief it &lt;em&gt;predates the bug
found by Grace Hopper in the Mark II computer&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The term was used by engineers way before that; at least since the 1870s.
It predates electronic computers and computer software.
Thomas Edison used the term “bug” in his notes.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Software_bug#Etymology&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bit&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bit&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Bit&lt;&#x2F;h2&gt;
&lt;p&gt;The term’s invention is credited to John W. Tukey, who in a memo written for
Bell Labs on January 9, 1947, had shortened “binary information digit” to “bit”.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Bit#History&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;byte&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#byte&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Byte&lt;&#x2F;h2&gt;
&lt;p&gt;The term “byte” was first introduced by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Werner_Buchholz&quot;&gt;Werner
Buchholz&lt;&#x2F;a&gt; in June 1956. This was
during the initial design stage for the IBM Stretch computer. The computer had a
design that enabled addressing down to the individual bit and allowed variable
field length instructions, with the size of the byte encoded into the
instruction itself. The choice of spelling as “byte” instead of “bite” was
intentional to prevent any accidental alteration to “bit”.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;carriage-return-and-line-feed&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#carriage-return-and-line-feed&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Carriage Return and Line Feed&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: Set the cursor to the beginning of the next line.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;These two terms were adopted from typewriters.&lt;&#x2F;p&gt;
&lt;p&gt;The carriage holds the paper and is moving from left to right to advance the
typing position as the keys are pressed. It “carries” the paper with it. The
carriage return is the operation when the carriage gets moved into its original
position on the very left end side of the paper.&lt;&#x2F;p&gt;
&lt;p&gt;Simply returning the carriage to the left is not enough to start with a new
line, however. The carriage would still be on the same line than before —
just at the beginning of the line. To go to a new line, a &lt;em&gt;line feed&lt;&#x2F;em&gt; was
needed. It would move the paper inside the typewriter up by one line.&lt;&#x2F;p&gt;
&lt;p&gt;These two operations — carriage return (CR) and line feed (LF) —
were commonly done at once by pushing the carriage return lever.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;typewriter-top.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;typewriter-top.jpg&quot; 
        
            alt=&quot;A mechanical typewriter. The lever for the carriage return is
on the outer left side.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;434&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            A mechanical typewriter. The lever for the carriage return is
on the outer left side.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: Source:
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.piqsels.com&#x2F;da&#x2F;public-domain-photo-spbhs&quot;&gt;piqsels&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;ul&gt;
&lt;li&gt;On Unix systems (like Linux or macOS), a &lt;code&gt;\n&lt;&#x2F;code&gt; still stands for a&lt;br &#x2F;&gt;
&lt;em&gt;line feed&lt;&#x2F;em&gt; (ASCII symbol: LF) or &lt;em&gt;newline&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;On CP&#x2F;M, DOS, and Windows, &lt;code&gt;\r\n&lt;&#x2F;code&gt; is used, where &lt;code&gt;\r&lt;&#x2F;code&gt; stands for
&lt;em&gt;carriage return&lt;&#x2F;em&gt; and &lt;code&gt;\n&lt;&#x2F;code&gt; stands for line feed (CR+LF).&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Newline&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here is an old video that shows the basic mechanics of carriage return and
line-feed:&lt;&#x2F;p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;EWfElq1vgLA&quot;
  
    data-start=&quot;842&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;typewriter.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;typewriter.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;command-key-symbol&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#command-key-symbol&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Command key symbol (⌘)&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A meta-key available on Apple computers to provide additional
keyboard combinations.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Directly quoting Wikipedia (emphasis mine):&lt;&#x2F;p&gt;
&lt;p&gt;The ⌘ symbol came into the Macintosh project at a late stage. The development
team originally went for their old Apple key, but Steve Jobs found it
frustrating when “apples” filled up the Mac’s menus next to the key commands,
because he felt that this was an over-use of the company logo. He then opted for
a different key symbol. With only a few days left before deadline, the team’s
bitmap artist Susan Kare started researching for the Apple logo’s successor. She
was browsing through a symbol dictionary when she came across the
cloverleaf-like symbol, commonly used in Nordic countries as an indicator of
cultural locations and &lt;strong&gt;places of interest&lt;&#x2F;strong&gt; (it is the official road sign for
tourist attraction in Denmark, Finland, Iceland, Norway, and Sweden and the
computer key has often been called Fornminne — ancient monument — by Swedish Mac
users and Seværdighedstegn by Danish users). When she showed it to the rest of
the team, everyone liked it, and so it became the symbol of the 1984 Macintosh
command key. Susan Kare states that it has since been told to her that the
symbol had been picked for its Scandinavian usage due to its resembling the
shape of a square castle with round corner towers as seen from above looking
down, notably Borgholm Castle.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;severdighet.png&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;severdighet.png&quot; 
        
            alt=&quot;Norwegian Severdighet road sign&quot;
        

        

        
        
        
            width=&quot;200&quot;
        
        
            height=&quot;200&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Norwegian Severdighet road sign
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Severdighet.svg&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;borgholm.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;borgholm.jpg&quot; 
        
            alt=&quot;Aearial view of Borgholm Castle, which could have been the model for the symbol &quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;434&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Aearial view of Borgholm Castle, which could have been the model for the symbol
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Borgholms_slottsruin_fr%C3%A5n_luften.jpg&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;References:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Command_key&quot;&gt;Wikipedia: Command Key&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.cultofmac.com&#x2F;181495&#x2F;what-are-the-macs-command-%E2%8C%98-and-option-%E2%8C%A5-symbols-supposed-to-represent&#x2F;&quot;&gt;Cult of Mac: What Are The Mac’s Command ⌘ And Option ⌥ Symbols Supposed To
Represent?&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;cookie&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#cookie&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Cookie&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A small piece of data sent from a website and stored in the
user’s web browser.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The term &lt;em&gt;cookie&lt;&#x2F;em&gt; was coined by  23-year-old web browser programmer Lou Montulli
in the fall of 1994. It was
inspired by the term &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Magic_cookie&quot;&gt;&lt;em&gt;magic cookie&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;, which is a packet of data a program
receives and sends back unchanged, used by Unix programmers.
This term in turn derives from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fortune_cookie&quot;&gt;fortune cookie&lt;&#x2F;a&gt;, which is a cookie with an embedded message.&lt;&#x2F;p&gt;
&lt;p&gt;Montulli used the
term &lt;em&gt;cookie&lt;&#x2F;em&gt; to describe the small packets of data that the web browser
receives and sends back unchanged to the web server.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“So, yeah, the cookie,” Montulli says with a laugh. “It’s one week of my life that turned into the most important thing that I ever did.” (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hiddenheroes.netguru.com&#x2F;lou-montulli&quot;&gt;Reference&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;core-dump&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#core-dump&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Core Dump&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: Retrieving a snapshot of a (crashed) program’s state by
storing all of its memory for offline analysis.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The name comes from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Magnetic-core_memory&quot;&gt;magnetic core
memory&lt;&#x2F;a&gt;, which is an early
storage mechanism based on a grid of toroid magnets. It has since become
obsolete, but the term is still used today for getting a snapshot of a computer
process. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Core_dump&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;corememory.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;corememory.jpg&quot; 
        
            alt=&quot;A 32 x 32 core memory plane storing
1024 bits (or 128 bytes) of data. The first core dumps were printed on paper, which sounds reasonable given these small amounts of bytes.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;650&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            A 32 x 32 core memory plane storing
1024 bits (or 128 bytes) of data. The first core dumps were printed on paper, which sounds reasonable given these small amounts of bytes.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:KL_CoreMemory.jpg&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;cursor&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#cursor&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Cursor&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: a visual cue (such as a flashing vertical line) on a video display that indicates position (as for data entry). &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.merriam-webster.com&#x2F;dictionary&#x2F;cursor&quot;&gt;Merriam-Webster&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Cursor&lt;&#x2F;em&gt; is Latin for &lt;em&gt;runner&lt;&#x2F;em&gt;. A cursor is the name given to the transparent
slide engraved with a hairline that is used for marking a point on a slide rule.
The term was then transferred to computers through analogy.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cursor_(user_interface)&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;slide-rule.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;slide-rule.jpg&quot; 
        
            alt=&quot;A December 1951 advertisement for the
IBM 604 Electronic Calculating Punch that was first produced in 1948. The
advertisement claims the IBM 604 can do the work of 150 engineers with slide
rules. The cursor (or runner) is the transparent part in the middle of the
slide.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;835&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: A December 1951 advertisement for the
IBM 604 Electronic Calculating Punch that was first produced in 1948. The
advertisement claims the IBM 604 can do the work of 150 engineers with slide
rules. The cursor (or runner) is the transparent part in the middle of the
slide.
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;daemon&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#daemon&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Daemon&lt;&#x2F;h2&gt;
&lt;p&gt;In computing, a daemon is a background process that handles requests for
services such as print spooling and file transfers, and then terminates. The
term was coined by the programmers of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.britannica.com&#x2F;topic&#x2F;Project-Mac&quot;&gt;MIT’s Project MAC (Mathematics and Computation)&lt;&#x2F;a&gt; in 1963. They took the name from
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Maxwell%27s_demon&quot;&gt;Maxwell’s demon&lt;&#x2F;a&gt;, a hypothetical creature from a thought experiment that
constantly works in the background, sorting molecules.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The MIT programmers thought demon would be an appropriate name for a background process that worked tirelessly to perform system chores. But instead of using the term demon, they used daemon, which is an older form of the word. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20230405225031&#x2F;https:&#x2F;&#x2F;www.techtarget.com&#x2F;whatis&#x2F;definition&#x2F;daemon&quot;&gt;Reference&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;dashboard&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#dashboard&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Dashboard&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A user interface that provides a quick overview of a system’s
status.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Originally a plank of wood at the front of a horse-drawn carriage to protect the
driver from mud ‘dashed’ backward by a horses hooves.&lt;&#x2F;p&gt;
&lt;p&gt;When automobiles were manufactured, the board in front of the driver was given
the same name. That was the logical place to put the necessary gauges so the
driver could see them easily. In time, the term became more associated with the
readouts than the protection it offered.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.quora.com&#x2F;What-common-phrases-are-derived-from-obsolete-technologies&#x2F;answer&#x2F;Geoffrey-Widdison&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;dashboard.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;dashboard.jpg&quot; 
        
            alt=&quot;A dashboard of a horse carriage.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;538&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            A dashboard of a horse carriage.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Dashboard_(PSF).png&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;firewall&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#firewall&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Firewall&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A network security system that establishes a barrier between a trusted internal network and an untrusted external network, such as the Internet.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Fire walls are used mainly in terraced houses, but also in individual residential buildings. They prevent fire and smoke from spreading to another part of the building in the event of a fire. Large fires can thus be prevented. The term is used in computing since the 80s.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Firewall_(computing)#History&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;firewall.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;firewall.jpg&quot; 
        
            alt=&quot;Firewall residential construction, separating the building into two separate residential units, and fire areas.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;655&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Firewall residential construction, separating the building into two separate residential units, and fire areas.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Brandwand_2.jpg&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;firmware&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#firmware&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Firmware&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A class of computer software that provides the low-level
control for the device’s specific hardware and closely tied to the hardware it runs on.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;archive.org&#x2F;details&#x2F;TNM_4th_generation_software_hardware_-_Datamation_20171010_0125&#x2F;mode&#x2F;2up&quot;&gt;Ascher
Opler&lt;&#x2F;a&gt;
coined the term &lt;em&gt;firmware&lt;&#x2F;em&gt; in a 1967 Datamation article. As originally used,
firmware contrasted with hardware (the CPU itself) and software (normal
instructions executing on a CPU). It existed on the boundary between hardware
and software; thus the name “firmware”. The original article is available on the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;archive.org&#x2F;details&#x2F;TNM_4th_generation_software_hardware_-_Datamation_20171010_0125&#x2F;mode&#x2F;2up&quot;&gt;Internet
Archive&lt;&#x2F;a&gt;.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Firmware&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;foo-and-bar&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#foo-and-bar&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Foo and Bar&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: Common placeholder variable names.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Originally the term might come from the military term &lt;em&gt;FUBAR&lt;&#x2F;em&gt;.
There are a few variations, but a common meaning is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_military_slang_terms#FUBAR&quot;&gt;FUBAR: “f***ed up beyond all recognition”&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The use of &lt;code&gt;foo&lt;&#x2F;code&gt; in a programming context is generally credited to the Tech
Model Railroad Club (TMRC) of MIT from circa 1960. In the complex model system,
there were scram switches located at numerous places around the room that could
be thrown if something undesirable was about to occur, such as a train going
full-bore at an obstruction.&lt;&#x2F;p&gt;
&lt;p&gt;The way I understood it was that they literally had emergency buttons labeled
&lt;code&gt;foo&lt;&#x2F;code&gt; for lack of a better name.
Maybe related to the original military meaning of FUBAR to indicate that something is going very very wrong.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;scram.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;scram.jpg&quot; 
        
            alt=&quot;A scram switch (button), that could be
pressed to prevent inadvertent operation. Maybe the TMRC had buttons labeled `foo` instead&quot;
        

        

        
        
        
            width=&quot;580&quot;
        
        
            height=&quot;480&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            A scram switch (button), that could be
pressed to prevent inadvertent operation. Maybe the TMRC had buttons labeled &lt;code&gt;foo&lt;&#x2F;code&gt; instead
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: Source &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:EBR-I_-_SCRAM_button.jpg&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;References:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Foobar#History_and_etymology&quot;&gt;Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;6727104&#x2F;270334&quot;&gt;Stack Overflow&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;freelancer&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#freelancer&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Freelancer&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A self-employed person, which is not committed to a particular employer long-term.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The term first appears in the novel &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Ivanhoe&quot;&gt;Ivanhoe&lt;&#x2F;a&gt; by Sir Walter Scott. (The novel also had a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Ivanhoe#Lasting_influence_on_the_Robin_Hood_legend&quot;&gt;lasting influence&lt;&#x2F;a&gt; on the Robin Hood legend.)&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;ivanhoe.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;ivanhoe.jpg&quot; 
        
            alt=&quot;Cover of a Classic Comics book&quot;
        

        

        
        
        
            width=&quot;512&quot;
        
        
            height=&quot;688&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Cover of a Classic Comics book
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:CC_No_02_Ivanhoe_2.jpg&quot;&gt;Wikimedia Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In it, a Lord offers his paid army of ‘free lances’ to King Richard:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I offered Richard the service of my Free Lances, and he refused them
— I will lead them to Hull, seize on shipping, and embark for Flanders;
thanks to the bustling times, a man of action will always find employment.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Therefore, a “free lancer” is someone who fights for whoever pays the most.
Free does not mean “without pay”, but refers to the additional freedom to work for any employer. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.merriam-webster.com&#x2F;words-at-play&#x2F;freelance-origin-meaning&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hash&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#hash&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Hash&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A hash function is any function that can be used to map data of arbitrary size to fixed-size values.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;According to Wikipedia, the use of the word “hash” in hash function
“comes by way of analogy with its non-technical meaning, to “chop and mix”.
Indeed, typical hash functions, like the mod operation, “chop” the input domain
into many sub-domains that get “mixed” into the output range to improve the
uniformity of the key distribution.“&lt;&#x2F;p&gt;
&lt;p&gt;References:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;softwareengineering.stackexchange.com&#x2F;a&#x2F;108127&quot;&gt;Software Engineering StackExchange&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hash_function#History&quot;&gt;Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;log-logfile&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#log-logfile&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Log &#x2F; Logfile&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A file that records events of a computer program or system.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Sailors used so-called log lines to measure the speed of their ship. A flat
piece of wood (the log) was attached to a long rope. The log had regularly
spaced knots in it. As the log would drift away, the sailors would count the
number of knots that went out in a fixed time interval, and this would be the
ship’s speed — in knots.&lt;&#x2F;p&gt;
&lt;p&gt;The ship’s speed was important for navigation, so the sailors noted it down in a book, aptly called the &lt;em&gt;log book&lt;&#x2F;em&gt;, together with other information to establish the position of the ship more accurately, like landmark sightings and weather events. Later, additional information, more generally concerning the ship, was added — or logged — such as harbor fees and abnormal provision depletion.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.usna.edu&#x2F;Users&#x2F;oceano&#x2F;pguth&#x2F;website&#x2F;shipwrecks&#x2F;logbooks_lesson&#x2F;logbooks_lesson.htm&quot;&gt;Reference&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;log-seamen.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;log-seamen.jpg&quot; 
        
            alt=&quot;Sailors measuring ship speed with a
log line&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;575&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Sailors measuring ship speed with a
log line
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sites.rootsweb.com&#x2F;~mosmd&#x2F;logln.htm&quot;&gt;The Pilgrims &amp;amp; Plymouth Colony:1620 by Duane A.
Cline&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;log-line.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;log-line.jpg&quot; 
        
            alt=&quot;The parts of a log-line&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;839&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            The parts of a log-line
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sites.rootsweb.com&#x2F;~mosmd&#x2F;logln.htm&quot;&gt;The
Pilgrims &amp;amp; Plymouth Colony:1620 by Duane A.
Cline&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;logfile.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;logfile.jpg&quot; 
        
            alt=&quot;Page from the log-file of the British
Winchelsea. The second column denotes the number of knots measured with the
log-line, which indicates the ship&amp;#x27;s speed&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;773&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Page from the log-file of the British
Winchelsea. The second column denotes the number of knots measured with the
log-line, which indicates the ship’s speed
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.usna.edu&#x2F;Users&#x2F;oceano&#x2F;pguth&#x2F;website&#x2F;shipwrecks&#x2F;logbooks_lesson&#x2F;logbooks_lesson.htm&quot;&gt;Navigation and Logbooks
in the Age of Sail by Peter
Reaveley&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;patch&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#patch&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Patch&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A piece of code that can be applied to fix or improve a
computer program.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In the early days of computing history, if you made a programming mistake, you’d
have to fix a paper tape or a punched card by putting a patch on top of a hole.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;patch.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;patch.jpg&quot; 
        
            alt=&quot;A program tape with physical patches used
to correct punched holes by covering them.&quot;
        

        

        
        
        
            width=&quot;639&quot;
        
        
            height=&quot;960&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            A program tape with physical patches used
to correct punched holes by covering them.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;americanhistory.si.edu&#x2F;archives&quot;&gt;Smithsonian Archives
Center&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;ping&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#ping&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Ping&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A way to check the availability and response time of a computer over the network.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Ping is a terminal program originally written by Mike Muuss in 1983 that is included in
every version of UNIX, Windows, and macOS. He named it “after the sound that a
sonar makes, inspired by the whole principle of echo-location. […] ping uses
timed &lt;code&gt;IP&#x2F;ICMP ECHO_REQUEST&lt;&#x2F;code&gt; and &lt;code&gt;ECHO_REPLY&lt;&#x2F;code&gt; packets to probe the “distance” to the
target machine.“ The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ftp.arl.army.mil&#x2F;~mike&#x2F;ping.html&quot;&gt;reference&lt;&#x2F;a&gt; is
well worth a read.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;pixel&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#pixel&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Pixel&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: The smallest controllable element of a picture represented on the screen.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The word pixel is a combination of &lt;em&gt;pix&lt;&#x2F;em&gt; (from “pictures”, shortened to “pics”) and &lt;em&gt;el&lt;&#x2F;em&gt; (for “element”).
Similarly, &lt;em&gt;voxel&lt;&#x2F;em&gt; is a volume element and &lt;em&gt;texel&lt;&#x2F;em&gt; is a texture element.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Pixel&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;shell&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#shell&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Shell&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: An interactive, commonly text-based runtime to interact with a
computer system.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The inventor of the term, Louis Pouzin, does not give an explanation for the
name in his essay &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.multicians.org&#x2F;shell.html&quot;&gt;The Origins of the
Shell&lt;&#x2F;a&gt;. It can however be traced back to
Unix’ predecessor Multics. It is described in the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.multicians.org&#x2F;mgs.html&quot;&gt;Multics
glossary&lt;&#x2F;a&gt; like so:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;[The shell] is passed a command line for execution by the &lt;strong&gt;listener&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The &lt;em&gt;The New Hacker’s Dictionary&lt;&#x2F;em&gt;, (also known as the &lt;em&gt;Jargon File&lt;&#x2F;em&gt;) by &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.catb.org&#x2F;~esr&#x2F;&quot;&gt;Eric S.
Raymond&lt;&#x2F;a&gt; contains &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.catb.org&#x2F;jargon&#x2F;html&#x2F;S&#x2F;shell.html&quot;&gt;the
following&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Historical note: Apparently, the original Multics shell (sense 1) was so
called because it was a shell (sense 3);&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;where sense 3 refers to&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;A skeleton program, created by hand or by another program (like, say, a parser
generator), which provides the necessary incantations to set up some task and
the control flow to drive it (the term driver is sometimes used synonymously).
The user is meant to fill in whatever code is needed to get real work done.
This usage is common in the AI and Microsoft Windows worlds, and confuses Unix
hackers.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Unfortunately, the book does not provide any evidence to back up this claim.&lt;&#x2F;p&gt;
&lt;p&gt;I like the (possibly historically incorrect) analogy to a nut with the shell
being on the outside, protecting the kernel.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;questions&#x2F;14934&#x2F;why-was-the-word-shell-used-to-descibe-a-command-line-interface&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;slab-allocator&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#slab-allocator&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Slab allocator&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: An efficient memory allocation technique, which reuses
previous allocations.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Slab allocation was invented by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.usenix.org&#x2F;publications&#x2F;library&#x2F;proceedings&#x2F;bos94&#x2F;full_papers&#x2F;bonwick.ps&quot;&gt;John
Bonwick&lt;&#x2F;a&gt;
(Note: PDF file) in 1994 and has since been used by services like
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.memcached.org&#x2F;&quot;&gt;Memcached&lt;&#x2F;a&gt; and the Linux Kernel.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;With slab allocation, a cache for a certain type or size of data object has a
number of pre-allocated “slabs” of memory; within each slab there are memory
chunks of fixed size suitable for the objects.
(&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Slab_allocation#Basis&quot;&gt;Wikpedia&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;The name &lt;em&gt;slab&lt;&#x2F;em&gt; comes from a teenage friend of Bonwick. He &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blogs.oracle.com&#x2F;bonwick&#x2F;now-it-can-be-told&quot;&gt;tells the
story&lt;&#x2F;a&gt; on the Oracle blog:&lt;&#x2F;p&gt;
&lt;p&gt;While watching TV together, a commercial by Kellogg’s came on with the tag line,
“Can you pinch an inch?”&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The implication was that you were overweight if you could pinch more than an
inch of fat on your waist — and that hoovering a bowl of corn flakes would
help.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;Without missing a beat, Tommy, who weighed about 250 pounds, reached for his
midsection and offered his response: “Hell, I can grab a slab!”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;A decade later, Bonwick remembered that term when he was looking for a word to
describe the allocation of a larger chunk of memory.&lt;&#x2F;p&gt;
&lt;p&gt;Here is the original Kellogg’s advertisement:&lt;&#x2F;p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;A8zYYg8wfmM&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;kellogs.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;kellogs.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;spam&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#spam&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Spam&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: Unsolicited electronic communications, for example by sending
mass-emails or posting in forums and chats.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The term goes back to a sketch by the British comedy group Monty Python from 1970.
In the sketch, a cafe is including
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Spam_(food)&quot;&gt;Spam&lt;&#x2F;a&gt; (a brand of canned cooked
pork) in almost every dish.
Spam is a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;time.com&#x2F;4827451&#x2F;spam-history-80th-anniversary&#x2F;&quot;&gt;portmanteau of &lt;em&gt;spiced&lt;&#x2F;em&gt; and &lt;em&gt;ham&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.
The excessive amount of Spam mentioned is a
reference to the ubiquity of it and other imported canned meat products in the
UK after World War II (a period of rationing in the UK) as the country struggled
to rebuild its agricultural base.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Spamming#Etymology&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;spam.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;spam.jpg&quot; 
        
            alt=&quot;Vintage Ad: Look What You Can Do With One
Can of Spam &quot;
        

        

        
        
        
            width=&quot;500&quot;
        
        
            height=&quot;734&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Vintage Ad: Look What You Can Do With One
Can of Spam
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: By user &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;jbcurio&#x2F;3878241798&quot;&gt;Jamie (jbcurio) on
flickr.com&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;player.vimeo.com&amp;#x2F;video&amp;#x2F;329001211&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;spam_preview.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;spam_preview.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimeo.com&#x2F;329001211&quot;&gt;Monty Pythons Flying Circus (1974) - SPAM&lt;&#x2F;a&gt; from
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimeo.com&#x2F;user97138516&quot;&gt;Testing Tester&lt;&#x2F;a&gt; on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vimeo.com&quot;&gt;Vimeo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mainframe&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#mainframe&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Mainframe&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A large computer system, often used by large organizations.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Originally, the term referred to the frame that held the main components of a
computer. The main components were the CPU, memory, and I&#x2F;O devices. The term
was used in the 1960s and 1970s when computers were large and required a lot of
space.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;mainframe.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;mainframe.jpg&quot; 
        
            alt=&quot;This diagram shows how the IBM 701 mainframe swings open for access to the circuitry. From &amp;#x27;Type 701 EDPM [Electronic Data Processing Machine] Installation Manual&amp;#x27;, IBM. From Computer History Museum archives.&quot;
        

        

        
        
        
            width=&quot;1930&quot;
        
        
            height=&quot;1378&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            This diagram shows how the IBM 701 mainframe swings open for access to the circuitry. From ‘Type 701 EDPM [Electronic Data Processing Machine] Installation Manual’, IBM. From Computer History Museum archives.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Read more about that on &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.righto.com&#x2F;2025&#x2F;02&#x2F;origin-of-mainframe-term.html&quot;&gt;Ken Shirriff’s blog&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;radio-button&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#radio-button&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Radio Button&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: A UI element that allows to choose from a predefined set of
mutually exclusive options&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;“Radio buttons” are named after the analogous pendant of mechanical buttons that
were used in radios. The UI concept has later been used in tape recorders,
cassette recorders and wearable audio players (the famous “Walkman” and
similar). And later in VCRs and video cameras.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.jitbit.com&#x2F;radio-button&#x2F;&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;radio-buttons.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;radio-buttons.jpg&quot; 
        
            alt=&quot;An old car radio (left) and CSS
radio buttons (right). Only a single option can be selected at any point in
time. As a kid, I would push two buttons at once so they would interlock. Good
times.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;295&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            An old car radio (left) and CSS
radio buttons (right). Only a single option can be selected at any point in
time. As a kid, I would push two buttons at once so they would interlock. Good
times.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: Images by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;themattcoady&quot;&gt;Matt Coady&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;uppercase-and-lowercase&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#uppercase-and-lowercase&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Uppercase and lowercase&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: Distinction between capital letters and small letters on a
keyboard.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Back when typesetting was a manual process where single letters made of led were
“type set” to form words and sentences, upper- and lowercase letters were kept
in separate containers — or cases — to make this rather tedious process a little faster.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;printers_cases.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;printers_cases.jpg&quot; 
        
            alt=&quot;A set of printers cases&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;575&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            A set of printers cases
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: From the book ‘Printing types, their history, forms, and use; a study in
survivals’ by Updike, Daniel Berkeley, 1860-1941. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;archive.org&#x2F;details&#x2F;printingtypesthe01updi&#x2F;&quot;&gt;Freely available on
archive.org&lt;&#x2F;a&gt;.
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;honorable-mentions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#honorable-mentions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Honorable mentions&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;404&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#404&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;404&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;em&gt;Today’s meaning: HTTP Status Code for “File not found”.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;There is a story that the number comes from the server room where the World Wide
Web’s central database was located. In there, administrators would manually
locate the requested files and transfer them, over the network, to the person
who made that request. If a file didn’t exist, they’d return an error message:
“Room 404: file not found”.&lt;&#x2F;p&gt;
&lt;p&gt;This, however, seems to be a myth and the status code was chosen rather
arbitrarily based on the then well-established FTP status codes.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;knowyourmeme.com&#x2F;memes&#x2F;404&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;programming-languages-and-abbreviations&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#programming-languages-and-abbreviations&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Programming languages and Abbreviations&lt;&#x2F;h2&gt;
&lt;p&gt;The etymology of programming language names and common abbreviations would
probably warrant its own article, but I’ve decided to note down some of my
favorites for the time being.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;c&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#c&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;C++&lt;&#x2F;h3&gt;
&lt;p&gt;C++ is a programming language based on C by Bjarne Stroustrup. The name is a
programmer pun by Rick Mascitti, a coworker of Stroustrup. The &lt;code&gt;++&lt;&#x2F;code&gt; refers to
the post-increment operator, that is common in many C-like languages. It
increases the value of a variable by 1. In that sense, C++ can be seen as the
spiritual “successor” of C.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;C%2B%2B#History&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;c-sharp&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#c-sharp&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;C Sharp&lt;&#x2F;h3&gt;
&lt;p&gt;Similarly to C++, C# is a C-like programming language. The name again refers to
“incremental” improvements on top of C++. The &lt;code&gt;#&lt;&#x2F;code&gt; in the name looks like four
plus signs. Hence &lt;code&gt;C# == (C++)++&lt;&#x2F;code&gt;. But on top of that, the name was also
inspired by the musical notation where a sharp indicates that the written note
should be made a semitone higher in pitch.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;C_Sharp_(programming_language)#Name&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;folklore&amp;#x2F;csharp.svg&quot; 
        
            alt=&quot;A C-Sharp note.&quot;
        

        

        
        
        
            width=&quot;274&quot;
        
        
            height=&quot;227&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            A C-Sharp note.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:Treblecsharp5.svg&quot;&gt;Wikimedia
Commons&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h3 id=&quot;png&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#png&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;PNG&lt;&#x2F;h3&gt;
&lt;p&gt;Officially, PNG stands for &lt;em&gt;Portable Network Graphics&lt;&#x2F;em&gt;. It was born out of
frustration over a CompuServe announcement in 1994 that programs supporting GIF
would have to pay licensing fees from now on. A working group lead by hacker
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;boutell.dev&#x2F;&quot;&gt;Thomas Boutell&lt;&#x2F;a&gt; created the &lt;code&gt;.webp&lt;&#x2F;code&gt; file format, a
patent-free replacement for GIF. Therefore I prefer the format’s unofficial
name: &lt;em&gt;PNG’s Not GIF&lt;&#x2F;em&gt;. Here’s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;people.apache.org&#x2F;~jim&#x2F;NewArchitect&#x2F;webrevu&#x2F;1997&#x2F;05_09&#x2F;designers&#x2F;05_09_97_1.html&quot;&gt;great
article&lt;&#x2F;a&gt;
on PNG’s history.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;encyclopedia2.thefreedictionary.com&#x2F;PNG%27s+Not+GIF&quot;&gt;Reference&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;credits&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#credits&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Credits&lt;&#x2F;h2&gt;
&lt;p&gt;Most of the content comes from sources like Wikipedia (with reference where
appropriate), but the explanations are difficult to hunt down if you don’t know
what you’re looking for.&lt;br &#x2F;&gt;
This is a living document, and I’m planning to update it in case of reader
submissions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#conclusion&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;You have to know the past to understand the present.&lt;br &#x2F;&gt;
— Dr. Carl Sagan (1980)&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I hope you enjoyed this trip down memory lane. Now it’s your turn!&lt;br &#x2F;&gt;
👉 Do you know any other stories? Send me a message, and I’ll add them here.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;related-projects&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#related-projects&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Related Projects&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;watson&#x2F;awesome-computer-history&quot;&gt;Awesome Computer History&lt;&#x2F;a&gt;:
A curated list of computer history videos, documentaries and related folklore
maintained by Thomas Watson.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_computer_term_etymologies&quot;&gt;Wikipedia: List of computer term etymologies&lt;&#x2F;a&gt;:
List of the origins of computer-related terms or terms used in the computing world.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=2KTK2qD4-gs&quot;&gt;Talk: The Etymology of Programming by Brittany Storoz - JSConf EU
2018&lt;&#x2F;a&gt;: A talk that explains the background behind a few programming terms. Careful here: the explanation for “bug” is probably wrong as mentioned above.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Typewriter#Terminology&quot;&gt;Typewriter terminology that has survived into the personal computer
era&lt;&#x2F;a&gt;:
A list of computer terms that have their origins from typewriters.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.folklore.org&quot;&gt;Folklore - The Original Macintosh&lt;&#x2F;a&gt;:
Anecdotes about the development of Apple’s original Macintosh, and the people who made it.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Timelapse of Timelapse</title>
        <published>2020-02-04T00:00:00+00:00</published>
        <updated>2020-02-04T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2020/timelapse/"/>
        <id>https://endler.dev/2020/timelapse/</id>
        
        <content type="html" xml:base="https://endler.dev/2020/timelapse/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;timelapse&quot;&gt;Timelapse&lt;&#x2F;a&gt; is a little open-source screen
recorder for macOS. It takes a screenshot every second and creates a movie in
the end.&lt;&#x2F;p&gt;
&lt;p&gt;To celebrate its unlikely 1.0 release today, I present here a “timelapse” of
this project’s journey. It just took &lt;em&gt;ten years&lt;&#x2F;em&gt; to get here.&lt;&#x2F;p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;_QEmxAZqQhE&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;timelapse.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;timelapse.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;2011-how-it-all-began&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#2011-how-it-all-began&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;2011 - How it all began&lt;&#x2F;h2&gt;
&lt;p&gt;To be honest, I don’t remember why I initially wrote the tool. I must have had a
personal need for a screen recorder, I guess…&lt;&#x2F;p&gt;
&lt;p&gt;In May 2011, when I started the project, I was doing my Masters Degree in
Computer Science. I might have needed the tool for University; most likely,
however, I was just trying to find an excuse for not working on an assignment.&lt;&#x2F;p&gt;
&lt;p&gt;During that time, I wrote a lot of tools like that. Mainly to scratch a personal
itch, learn a new programming language, or just have fun.&lt;&#x2F;p&gt;
&lt;p&gt;Among them are tools like a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;ihatesubways&quot;&gt;random sandwich
generator&lt;&#x2F;a&gt; for Subway (the American
fast-food chain), &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;DrawRoom&quot;&gt;DrawRoom&lt;&#x2F;a&gt;, a keyboard-driven
drawing app inspired by
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;www.hogbaysoftware.com&#x2F;products&#x2F;writeroom&quot;&gt;WriteRoom&lt;&#x2F;a&gt;, and the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;Creamy&quot;&gt;obligatory CMS software&lt;&#x2F;a&gt;, that I sold to
clients. Surprisingly, none of them were a great success.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;timelapse&amp;#x2F;drawroom.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2020&amp;#x2F;timelapse&amp;#x2F;drawroom.jpg&quot; 
        
            alt=&quot;DrawRoom, a tool that I wrote around the same time, is a real piece of art. To this day it has five commits and a single Github star (by myself, don&amp;#x27;t judge...).&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;393&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            DrawRoom, a tool that I wrote around the same time, is a real piece of art. To this day it has five commits and a single Github star (by myself, don’t judge…).
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;What I &lt;em&gt;do&lt;&#x2F;em&gt; know for sure is that I was unhappy with all existing screen
recorders. They could roughly be categorized into these three groups:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Proprietary solutions that cost money or could call home.&lt;&#x2F;li&gt;
&lt;li&gt;Tools that didn’t work on macOS.&lt;&#x2F;li&gt;
&lt;li&gt;Small, fragile, one-off scripts that people passed around in forums or as
Github gists. They rarely worked as advertised.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Among the remaining tools were none that provided any timelapse functionality;
so I set out to write my own.&lt;&#x2F;p&gt;
&lt;p&gt;This all sounds very epic, but in reality, I worked on it for a day. After five
heroic commits on May 11, 2011, it sat there, idle, for seven years…&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2018&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#2018&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;2018&lt;&#x2F;h2&gt;
&lt;p&gt;A lot of time elapsed before anything exciting happened.&lt;&#x2F;p&gt;
&lt;p&gt;In January ’18, seemingly out of nowhere, the first user filed a bug report. It
was titled &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;timelapse&#x2F;issues&#x2F;1&quot;&gt;hung when creating the
avi&lt;&#x2F;a&gt; 😱. Turns out that a game
developer from Canada,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;channel&#x2F;UCs2DJ9xpGic1pQkWNMwAUHw&quot;&gt;juul1a&lt;&#x2F;a&gt;, was trying
to use the tool to track her progress on an indie game — how cool is that?&lt;&#x2F;p&gt;
&lt;p&gt;To help her out, I decided to do some general cleanup, finally write down some
instructions on how to even use the program, add a &lt;code&gt;requirements.txt&lt;&#x2F;code&gt;, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;timelapse&#x2F;commit&#x2F;0b43515037670604143bf3b3eb06061ecfbbe108&quot;&gt;port
the tool from mencoder to
ffmpeg&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;After that, timelapse was ready for prime-time. 🎬 Here is some live action from
her videos featuring timelapses:&lt;&#x2F;p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;vv2CCwEM8Ws&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;preview.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;preview.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;p&gt;At that point, the tool was still very wobbly and could only be used from the
commandline, but I began to see some potential for building a proper app from
it; I just never found the &lt;em&gt;time&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In October ’18, I decided to ask for support during
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hacktoberfest.digitalocean.com&#x2F;&quot;&gt;Hacktoberfest&lt;&#x2F;a&gt;. I created a few
tickets and labeled them with &lt;code&gt;hacktoberfest&lt;&#x2F;code&gt; to try and find contributors.&lt;&#x2F;p&gt;
&lt;p&gt;And then, I waited.&lt;&#x2F;p&gt;
&lt;p&gt;First, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ShreyaPrabhu&quot;&gt;Shreya V Prabhu&lt;&#x2F;a&gt; fixed an issue where a
new recording was overwriting the previous one by adding a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;timelapse&#x2F;pull&#x2F;3&quot;&gt;timestamp to the
video name&lt;&#x2F;a&gt;. Then &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;abnerpc&quot;&gt;Abner
Campanha&lt;&#x2F;a&gt; and Shane
Creedon (no longer on Github) created a basic test structure.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;seleregb&quot;&gt;Gbenro Selere&lt;&#x2F;a&gt; added a CI pipeline for Travis CI.
It really worked, and the project was in much better shape after that!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2019&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#2019&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;2019&lt;&#x2F;h2&gt;
&lt;p&gt;One year passes by, and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Kerl1310&quot;&gt;Kyle Jones&lt;&#x2F;a&gt; adds some
contribution guidelines, while I move the CI pipeline to the newly released
Github actions.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cmangla&quot;&gt;Chaitanya&lt;&#x2F;a&gt; fixed a bug where the program would hang when
the recording stopped by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;timelapse&#x2F;pull&#x2F;24&quot;&gt;moving the video creation from threads to a separate
process&lt;&#x2F;a&gt;. He continued to make the
codebase more robust and became a core contributor, reviewing pull requests and
handling releases.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;orcutt989&quot;&gt;orcutt989&lt;&#x2F;a&gt;, the app now made use of
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;timelapse&#x2F;pull&#x2F;33&quot;&gt;type hints in Python 3.6&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gkpln3&quot;&gt;gkpln3&lt;&#x2F;a&gt; added support for multi-monitor
configurations. The screen captured will always be the one with the mouse on it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2020&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#2020&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;2020&lt;&#x2F;h2&gt;
&lt;p&gt;Fast forward to today, and after almost &lt;em&gt;ten years&lt;&#x2F;em&gt;, we finally created a true
macOS app using the awesome &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ronaldoussoren&#x2F;py2app&quot;&gt;py2app&lt;&#x2F;a&gt;
bundler. This should make the tool usable by non-developers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;back-to-the-future&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#back-to-the-future&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Back to the Future&lt;&#x2F;h2&gt;
&lt;p&gt;We reached the end of our little journey.&lt;&#x2F;p&gt;
&lt;p&gt;A long time has passed until 1.0. This project is a testament to the wonders of
open source collaboration, and I am proud to work on it with contributors from
around the world. It doesn’t have to be a life-changing project to bring people
together who have fun building things. If this were the end of the story, I’d be
okay with that. I doubt it, though. Here’s to the next ten years!&lt;&#x2F;p&gt;
&lt;p&gt;🎬 &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;timelapse&quot;&gt;Download timelapse on Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bonus&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bonus&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Bonus&lt;&#x2F;h2&gt;
&lt;p&gt;The video at the beginning is a timelapse of how I finish this article.&lt;br &#x2F;&gt;
How meta.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Github Stars</title>
        <published>2020-01-01T00:00:00+00:00</published>
        <updated>2020-01-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/static/about/stars/"/>
        <id>https://endler.dev/static/about/stars/</id>
        
        <content type="html" xml:base="https://endler.dev/static/about/stars/">&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th style=&quot;text-align: left&quot;&gt;Repository&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;Stars&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;analysis-tools-dev&#x2F;static-analysis&quot;&gt;analysis-tools-dev&#x2F;static-analysis&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;14464 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;idiomatic-rust&quot;&gt;mre&#x2F;idiomatic-rust&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;7628 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lycheeverse&#x2F;lychee&quot;&gt;lycheeverse&#x2F;lychee&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;3462 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tinysearch&#x2F;tinysearch&quot;&gt;tinysearch&#x2F;tinysearch&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;2922 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;the-coding-interview&quot;&gt;mre&#x2F;the-coding-interview&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1742 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;analysis-tools-dev&#x2F;dynamic-analysis&quot;&gt;analysis-tools-dev&#x2F;dynamic-analysis&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1079 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ReceiptManager&#x2F;receipt-parser-legacy&quot;&gt;ReceiptManager&#x2F;receipt-parser-legacy&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;852 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;hyperjson&quot;&gt;mre&#x2F;hyperjson&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;510 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lycheeverse&#x2F;lychee-action&quot;&gt;lycheeverse&#x2F;lychee-action&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;471 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;cargo-inspect&quot;&gt;mre&#x2F;cargo-inspect&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;384 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hello-rust&#x2F;show&quot;&gt;hello-rust&#x2F;show&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;319 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;fcat&quot;&gt;mre&#x2F;fcat&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;282 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;vscode-snippet&quot;&gt;mre&#x2F;vscode-snippet&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;255 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;kafka-influxdb&quot;&gt;mre&#x2F;kafka-influxdb&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;217 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ReceiptManager&#x2F;receipt-manager-app&quot;&gt;ReceiptManager&#x2F;receipt-manager-app&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;214 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;timelapse&quot;&gt;mre&#x2F;timelapse&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;212 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;prettyprint&quot;&gt;mre&#x2F;prettyprint&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;201 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;zerocal&quot;&gt;mre&#x2F;zerocal&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;173 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;endler.dev&quot;&gt;mre&#x2F;endler.dev&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;108 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;mos6502&quot;&gt;mre&#x2F;mos6502&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;106 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td style=&quot;text-align: left&quot;&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ReceiptManager&#x2F;receipt-parser-server&quot;&gt;ReceiptManager&#x2F;receipt-parser-server&lt;&#x2F;a&gt;&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;103 ★&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Tiny, Static, Full-Text Search Engine using Rust and WebAssembly</title>
        <published>2019-10-17T00:00:00+00:00</published>
        <updated>2022-02-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2019/tinysearch/"/>
        <id>https://endler.dev/2019/tinysearch/</id>
        
        <content type="html" xml:base="https://endler.dev/2019/tinysearch/">&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;I wrote a basic search module that you can add to a static website.
It’s very lightweight (50kB-100kB gzipped) and works with Hugo, Zola, and
Jekyll. Only searching for entire words is supported. Try the search box on the
left for a demo. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;tinysearch&quot;&gt;The code is on Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;Static site generators are magical. They combine the best of both worlds:
dynamic content without sacrificing performance.&lt;&#x2F;p&gt;
&lt;p&gt;Over the years, this blog has been running on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;mre.github.io.v1&quot;&gt;Jekyll&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;mre.github.io.v2&quot;&gt;Cobalt&lt;&#x2F;a&gt;, and, lately,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;One thing I always disliked, however, was the fact that static websites don’t
come with “static” search engines, too. Instead, people resort to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cse.google.com&#x2F;about&quot;&gt;custom Google
searches&lt;&#x2F;a&gt;, external search engines like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.algolia.com&#x2F;&quot;&gt;Algolia&lt;&#x2F;a&gt;, or pure
JavaScript-based solutions like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lunrjs.com&#x2F;&quot;&gt;lunr.js&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;elasticlunr.com&#x2F;&quot;&gt;elasticlunr&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;All of these work fine for most sites, but it never felt like the final answer.&lt;&#x2F;p&gt;
&lt;p&gt;I didn’t want to add yet another dependency on Google; neither did I want to use
a stand-alone web-backend like Algolia, which adds latency and is proprietary.&lt;&#x2F;p&gt;
&lt;p&gt;On the other side, I’m not a huge fan of JavaScript-heavy websites. For example,
just the search indices that lunr creates can be &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;olivernn&#x2F;lunr.js&#x2F;issues&#x2F;268#issuecomment-304490937&quot;&gt;multiple megabytes
in size&lt;&#x2F;a&gt;.
That feels lavish - even by today’s bandwidth standards. On top of that,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;v8.dev&#x2F;blog&#x2F;cost-of-javascript-2019&quot;&gt;parsing JavaScript is still
time-consuming&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I wanted some simple, lean, and self-contained search, that could be deployed
next to my other static content.&lt;&#x2F;p&gt;
&lt;p&gt;As a consequence, I refrained from adding search functionality to my blog at
all. That’s unfortunate because, with a growing number of articles, it gets
harder and harder to find relevant content.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-idea&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-idea&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Idea&lt;&#x2F;h2&gt;
&lt;p&gt;Many years ago, in 2013, I read &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stavros.io&#x2F;posts&#x2F;bloom-filter-search-engine&#x2F;&quot;&gt;“Writing a full-text search engine using Bloom
filters”&lt;&#x2F;a&gt; — and it was a revelation.&lt;&#x2F;p&gt;
&lt;p&gt;The idea was simple: Let’s run all my blog articles through a generator that
creates a tiny, self-contained search index using this magical data structure
called a
✨&lt;em&gt;Bloom Filter&lt;&#x2F;em&gt; ✨.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;wait-what-s-a-bloom-filter&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#wait-what-s-a-bloom-filter&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Wait, what’s a Bloom Filter?&lt;&#x2F;h2&gt;
&lt;p&gt;A &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Bloom_filter&quot;&gt;Bloom filter&lt;&#x2F;a&gt; is a space-efficient way to
check if an element is in a set.&lt;&#x2F;p&gt;
&lt;p&gt;The trick is that it doesn’t store the elements themselves; it just knows with
some confidence that they were stored before. In our case, it can say with a
certain &lt;em&gt;error rate&lt;&#x2F;em&gt; that a word is in an article.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2019&amp;#x2F;tinysearch&amp;#x2F;bloomfilter.svg&quot; 
        
            alt=&quot;A Bloom filter stores a
&amp;#x27;fingerprint&amp;#x27; (a number of hash values) of all input values instead of the raw
input. The result is a low-memory-footprint data structure. This is an example
of &amp;#x27;hello&amp;#x27; as an input.&quot;
        

        

        
        
        
            width=&quot;345&quot;
        
        
            height=&quot;230&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            A Bloom filter stores a
‘fingerprint’ (a number of hash values) of all input values instead of the raw
input. The result is a low-memory-footprint data structure. This is an example
of ‘hello’ as an input.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Here’s the Python code from the original article that generates the Bloom
filters for each post (courtesy of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stavros.io&quot;&gt;Stavros
Korokithakis&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;filters&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;for&lt;&#x2F;span&gt;&lt;span&gt; name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; words&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; split_posts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;items&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  filters&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; BloomFilter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;capacity&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;words&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; error_rate&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0.1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span&gt; word&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; in&lt;&#x2F;span&gt;&lt;span&gt; words&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    filters&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;add&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;word&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The memory footprint is extremely small, thanks to &lt;code&gt;error_rate&lt;&#x2F;code&gt;, which allows
for a negligible number of false positives.&lt;&#x2F;p&gt;
&lt;p&gt;I immediately knew that I wanted something like this for my homepage. My idea
was to directly ship the Bloom filters and the search engine to the browser. I
could finally have a small, static search without the need for a backend!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;headaches&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#headaches&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Headaches&lt;&#x2F;h2&gt;
&lt;p&gt;Disillusionment came quickly.&lt;&#x2F;p&gt;
&lt;p&gt;I had no idea how to bundle and minimize the generated Bloom filters, let alone
run them on clients. The original article briefly touches on this:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;You need to implement a Bloom filter algorithm on the client-side. This will
probably not be much longer than the inverted index search algorithm, but it’s
still probably a bit more complicated.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I didn’t feel confident enough in my JavaScript skills to pull this off. Back in
2013, NPM was a mere three years old, and WebPack just turned one, so I also
didn’t know where to look for existing solutions.&lt;&#x2F;p&gt;
&lt;p&gt;Unsure what to do next, my idea remained a pipe dream.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-new-hope&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a-new-hope&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;A New Hope&lt;&#x2F;h2&gt;
&lt;p&gt;Five years later, in 2018, the web had become a different place. Bundlers were
ubiquitous, and the Node ecosystem was flourishing. One thing, in particular,
revived my dreams about the tiny static search engine: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;webassembly.org&#x2F;&quot;&gt;WebAssembly&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;WebAssembly (abbreviated Wasm) is a binary instruction format for a
stack-based virtual machine. Wasm is designed as a portable target for
compilation of high-level languages like C&#x2F;C++&#x2F;Rust, enabling deployment on
the web for client and server applications. [&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;webassembly.org&#x2F;&quot;&gt;source&lt;&#x2F;a&gt;]&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;This meant that I could use a language that I was familiar with to write the
client-side code — Rust! 🎉&lt;&#x2F;p&gt;
&lt;p&gt;My journey started with a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;tinysearch&#x2F;commit&#x2F;82c1d36835348718f04c9ca0dd2c1ebf8b19a312&quot;&gt;prototype back in January
2018&lt;&#x2F;a&gt;.
It was just a direct port of the Python version from above:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; filters&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; HashMap&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; words&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; articles&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; BloomFilter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;with_rate&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; words&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; word&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; words&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;word&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  filters&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;While I managed to create the Bloom filters for every article, I &lt;em&gt;still&lt;&#x2F;em&gt; had no
clue how to package it for the web… until &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-pack&#x2F;commit&#x2F;125431f97eecb6f3ca5122f8b345ba5b7eee94c7&quot;&gt;wasm-pack came along in
February
2018&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;whoops-i-shipped-some-rust-code-to-your-browser&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#whoops-i-shipped-some-rust-code-to-your-browser&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Whoops! I Shipped Some Rust Code To Your Browser.&lt;&#x2F;h2&gt;
&lt;p&gt;Now I had all the pieces of the puzzle:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Rust — A language I was comfortable with&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-pack&quot;&gt;wasm-pack&lt;&#x2F;a&gt; — A bundler for WebAssembly modules&lt;&#x2F;li&gt;
&lt;li&gt;A working prototype that served as a proof-of-concept&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The search box you see on the left side of this page is the outcome. It fully runs on Rust using
WebAssembly (a.k.a the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;timClicks&#x2F;status&#x2F;1181822319620063237&quot;&gt;RAW stack&lt;&#x2F;a&gt;). Try it now if you like.&lt;&#x2F;p&gt;
&lt;p&gt;There were quite a few obstacles along the way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;bloom-filter-crates&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bloom-filter-crates&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Bloom Filter Crates&lt;&#x2F;h2&gt;
&lt;p&gt;I looked into a few Rust libraries (crates) that implement Bloom filters.&lt;&#x2F;p&gt;
&lt;p&gt;First, I tried jedisct1’s
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jedisct1&#x2F;rust-bloom-filter&quot;&gt;rust-bloom-filter&lt;&#x2F;a&gt;, but the types
didn’t implement
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.serde.rs&#x2F;serde&#x2F;trait.Serialize.html&quot;&gt;Serialize&lt;&#x2F;a&gt;&#x2F;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.serde.rs&#x2F;serde&#x2F;trait.Deserialize.html&quot;&gt;Deserialize&lt;&#x2F;a&gt;.
This meant that I could not store my generated Bloom filters inside the binary and load
them on the client-side.&lt;&#x2F;p&gt;
&lt;p&gt;After trying a few others, I found the
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;seiflotfy&#x2F;rust-cuckoofilter&quot;&gt;cuckoofilter&lt;&#x2F;a&gt; crate, which
supported serialization. The behavior is similar to Bloom filters, but if you’re
interested in the differences, you can look at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;brilliant.org&#x2F;wiki&#x2F;cuckoo-filter&#x2F;&quot;&gt;this
summary&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s how to use it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; cf&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; cuckoofilter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Add data to the filter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; value&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello world&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; success&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; cf&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;add&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;value&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Lookup if data was added before&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; success&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; cf&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;contains&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;value&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; success ==&amp;gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let’s check the output size when bundling the filters for ten articles on my blog using cuckoo filters:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;~&#x2F;C&#x2F;p&#x2F;tinysearch ❯❯❯ l storage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Permissions Size User    Date Modified Name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.rw-r--r--   44k mendler 24 Mar 15:42  storage&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;44kB&lt;&#x2F;strong&gt; doesn’t sound too shabby, but these are just the cuckoo filters for ten
articles, serialized as a Rust binary. On top of that, we have to add the search
functionality and the helper code. In total, the client-side code weighed in at
&lt;strong&gt;216kB&lt;&#x2F;strong&gt; using vanilla wasm-pack. Too much.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;trimming-binary-size&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#trimming-binary-size&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Trimming Binary Size&lt;&#x2F;h2&gt;
&lt;p&gt;After the sobering first result of 216kB for our initial prototype, we have a
few options to bring the binary size down.&lt;&#x2F;p&gt;
&lt;p&gt;The first is following &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;johnthagen&quot;&gt;johnthagen’s&lt;&#x2F;a&gt; advice on
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;johnthagen&#x2F;min-sized-rust&quot;&gt;minimizing Rust binary size&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;By setting a few options in our &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;, we can shave off quite a few bytes:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;opt-level = &amp;#39;z&amp;#39;&amp;quot; =&amp;gt; 249665 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;lto = true&amp;quot;      =&amp;gt; 202516 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;opt-level = &amp;#39;s&amp;#39;&amp;quot; =&amp;gt; 195950 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Setting &lt;code&gt;opt-level&lt;&#x2F;code&gt; to &lt;code&gt;s&lt;&#x2F;code&gt; means we trade size for speed,
but we’re preliminarily interested in minimal size anyway. After all, a small download size also improves performance.&lt;&#x2F;p&gt;
&lt;p&gt;Next, we can try &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wee_alloc&quot;&gt;wee_alloc&lt;&#x2F;a&gt;, an alternative Rust allocator
producing a small &lt;code&gt;.wasm&lt;&#x2F;code&gt; code size.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It is geared towards code that makes a handful of initial dynamically sized allocations, and then performs its heavy lifting without any further allocations. This scenario requires some allocator to exist, but we are more than happy to trade allocation performance for small code size.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Exactly what we want. Let’s try!&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;wee_alloc and nightly&amp;quot; =&amp;gt; 187560 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We shaved off another 4% from our binary.&lt;&#x2F;p&gt;
&lt;p&gt;Out of curiosity, I tried to set &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;rustc&#x2F;codegen-options&#x2F;index.html#codegen-units&quot;&gt;codegen-units&lt;&#x2F;a&gt; to 1, meaning we only use a single thread for code generation. Surprisingly, this resulted in a slightly smaller binary size.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;codegen-units = 1&amp;quot; =&amp;gt; 183294 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then I got word of a Wasm optimizer called &lt;code&gt;binaryen&lt;&#x2F;code&gt;.
On macOS, it’s available through homebrew:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;brew install binaryen&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It ships a binary called &lt;code&gt;wasm-opt&lt;&#x2F;code&gt; and that shaved off another 15%:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;quot;wasm-opt -Oz&amp;quot; =&amp;gt; 154413 bytes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then I removed web-sys as we don’t have to bind to the DOM: 152858 bytes.&lt;&#x2F;p&gt;
&lt;p&gt;There’s a tool called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;twiggy&quot;&gt;twiggy&lt;&#x2F;a&gt; to profile the code size of Wasm binaries.
It printed the following output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;twiggy top -n 20 pkg&#x2F;tinysearch_bg.wasm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt; Shallow Bytes │ Shallow % │ Item&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;─────────────┼───────────┼────────────────────────────────&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         79256 ┊    44.37% ┊ data[0]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;         13886 ┊     7.77% ┊ &amp;quot;function names&amp;quot; subsection&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          7289 ┊     4.08% ┊ data[1]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          6888 ┊     3.86% ┊ core::fmt::float::float_to_decimal_common_shortest::hdd201d50dffd0509&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          6080 ┊     3.40% ┊ core::fmt::float::float_to_decimal_common_exact::hcb5f56a54ebe7361&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          5972 ┊     3.34% ┊ std::sync::once::Once::call_once::{{closure}}::ha520deb2caa7e231&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          5869 ┊     3.29% ┊ search&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;From what I can tell, the biggest chunk of our binary is occupied by the raw data section for our articles.
Next up, we got the function headers and some float to decimal helper functions, that most likely come from deserialization.&lt;&#x2F;p&gt;
&lt;p&gt;Finally, I tried &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rustwasm&#x2F;wasm-snip&quot;&gt;wasm-snip&lt;&#x2F;a&gt;, which replaces a WebAssembly function’s body with an &lt;code&gt;unreachable&lt;&#x2F;code&gt; like so, but it didn’t reduce code size:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;wasm-snip --snip-rust-fmt-code --snip-rust-panicking-code -o pkg&#x2F;tinysearch_bg_snip.wasm pkg&#x2F;tinysearch_bg_opt.wasm&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After tweaking with the parameters of the cuckoo filters a bit and removing
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Stop_words&quot;&gt;stop words&lt;&#x2F;a&gt; from the articles, I
arrived at &lt;strong&gt;121kB&lt;&#x2F;strong&gt; (51kB gzipped) — not bad considering the average image size on the web is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;httparchive.org&#x2F;reports&#x2F;state-of-images#bytesImg&quot;&gt;around 900kB&lt;&#x2F;a&gt;.
On top of that, the search functionality only gets loaded when a user clicks into the search field.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;update&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#update&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Update&lt;&#x2F;h2&gt;
&lt;p&gt;Recently I moved the project from cuckoofilters to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;arxiv.org&#x2F;abs&#x2F;1912.08258&quot;&gt;XOR filters&lt;&#x2F;a&gt;.
I used the awesome &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;ayazhafiz&#x2F;xorf&quot;&gt;xorf&lt;&#x2F;a&gt; project, which comes with built-in serde serialization.
which allowed me to remove a lot of custom code.&lt;&#x2F;p&gt;
&lt;p&gt;With that, I could reduce the payload size by another 20-25% percent. I’m down to &lt;strong&gt;99kB&lt;&#x2F;strong&gt; (&lt;strong&gt;49kB gzipped&lt;&#x2F;strong&gt;) on my blog now. 🎉&lt;&#x2F;p&gt;
&lt;p&gt;The new version is released &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;tinysearch&quot;&gt;on crates.io&lt;&#x2F;a&gt; already, if you want to give it a try.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;frontend-and-glue-code&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#frontend-and-glue-code&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Frontend- and Glue Code&lt;&#x2F;h2&gt;
&lt;p&gt;wasm-pack will auto-generate the JavaScript code to talk to Wasm.&lt;&#x2F;p&gt;
&lt;p&gt;For the search UI, I customized a few JavaScript and CSS bits from
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.w3schools.com&#x2F;howto&#x2F;tryit.asp?filename=tryhow_js_autocomplete&quot;&gt;w3schools&lt;&#x2F;a&gt;.
It even has keyboard support!
Now when a user enters a search query, we go through the cuckoo filter of each
article and try to match the words. The results are scored by the number of
hits. Thanks to my dear colleague &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jorgelbg&#x2F;&quot;&gt;Jorge Luis Betancourt&lt;&#x2F;a&gt; for adding that part.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2019&amp;#x2F;tinysearch&amp;#x2F;anim-opt2.gif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2019&amp;#x2F;tinysearch&amp;#x2F;anim-opt2.gif&quot; 
        
            alt=&quot;Video of the search functionality&quot;
        

        

        
        
        
            width=&quot;600&quot;
        
        
            height=&quot;238&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Video of the search functionality
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;(Fun fact: this animation is about the same size as the uncompressed Wasm search itself.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;caveats&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#caveats&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Caveats&lt;&#x2F;h2&gt;
&lt;p&gt;Only whole words are matched. I would love to add prefix-search, but the
binary became too big when I tried.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;usage&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#usage&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Usage&lt;&#x2F;h2&gt;
&lt;p&gt;The standalone binary to create the Wasm file is called &lt;code&gt;tinysearch&lt;&#x2F;code&gt;.
It expects a single path to a JSON file as an input:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;tinysearch path&#x2F;to&#x2F;corpus.json&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This &lt;code&gt;corpus.json&lt;&#x2F;code&gt; contains the text you would like to index. The format is pretty straightforward:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Article 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;example.com&#x2F;article1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;This is the body of article 1.&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;title&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Article 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;example.com&#x2F;article2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;body&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-support z-type z-property-name&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;This is the body of article 2.&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can generate this JSON file with any static site generator.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;mre.github.io&#x2F;tree&#x2F;1c731717b48afb584e54ca4dd5fd649f9b74e51c&#x2F;templates&quot;&gt;Here’s my version for Zola&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% set section = get_section(path=&amp;quot;_index.md&amp;quot;) %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {%- for post in section.pages -%}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {% if not post.draft %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;quot;title&amp;quot;: {{ post.title | striptags | json_encode | safe }},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;quot;url&amp;quot;: {{ post.permalink | json_encode | safe }},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;quot;body&amp;quot;: {{ post.content | striptags | json_encode | safe }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      {% if not loop.last %},{% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    {% endif %}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  {%- endfor -%}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I’m pretty sure that the Jekyll version looks quite similar.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;learn.cloudcannon.com&#x2F;jekyll&#x2F;output-json&#x2F;&quot;&gt;Here’s a starting point&lt;&#x2F;a&gt;.
If you get something working for your static site generator, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tinysearch&#x2F;tinysearch&#x2F;tree&#x2F;master&#x2F;howto&quot;&gt;please let me know&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;observations&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#observations&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Observations&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;This is still the wild west: unstable features, nightly Rust, documentation
gets outdated almost every day.&lt;br &#x2F;&gt;
Bring your thinking cap!&lt;&#x2F;li&gt;
&lt;li&gt;Creating a product out of a good idea is a lot of work. One has to pay
attention to many factors: ease-of-use, generality, maintainability,
documentation, and so on.&lt;&#x2F;li&gt;
&lt;li&gt;Rust is very good at removing dead code, so you usually don’t pay for what
you don’t use. I would still advise you to be very conservative about the
dependencies you add to a Wasm binary because it’s tempting to add features
that you don’t need and which will add to the binary size. For example, I
used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TeXitoi&#x2F;structopt&quot;&gt;StructOpt&lt;&#x2F;a&gt; during testing, and I had a &lt;code&gt;main()&lt;&#x2F;code&gt; function that was parsing
these command-line arguments. This was not necessary for Wasm, so I
removed it later.&lt;&#x2F;li&gt;
&lt;li&gt;I understand that not everyone wants to write Rust code. It’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;go-vs-rust&#x2F;&quot;&gt;complicated to
get started with&lt;&#x2F;a&gt;, but the cool thing is that you can
use almost any other language, too. For example, you can write Go code and
transpile to Wasm, or maybe you prefer PHP or Haskell. There is support for
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;appcypher&#x2F;awesome-wasm-langs&quot;&gt;many languages&lt;&#x2F;a&gt; already.&lt;&#x2F;li&gt;
&lt;li&gt;A lot of people dismiss WebAssembly as a toy technology. They couldn’t be
further from the truth. In my opinion, WebAssembly will revolutionize the way we build
products for the web and beyond. What was very hard just two years ago is now
easy: shipping code in any language to every browser. I’m super excited about
its future.&lt;&#x2F;li&gt;
&lt;li&gt;If you’re looking for a standalone, self-hosted search index for your company
website, check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;journal.valeriansaliou.name&#x2F;announcing-sonic-a-super-light-alternative-to-elasticsearch&#x2F;&quot;&gt;sonic&lt;&#x2F;a&gt;.
Also check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;jameslittle230&#x2F;stork&quot;&gt;stork&lt;&#x2F;a&gt; as an alternative.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;try-it&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#try-it&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Try it!&lt;&#x2F;h2&gt;
&lt;p&gt;The code for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;tinysearch&quot;&gt;tinysearch is on Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Please be aware of these limitations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Only searches for entire words.&lt;&#x2F;strong&gt; There are no search suggestions.
The reason is that prefix search blows up binary size like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=b6u9WJ01Oxs&quot;&gt;Mentos and Diet Coke&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Since we bundle all search indices for all articles into one static binary, I
&lt;strong&gt;only recommend to use it for low- to medium-sized websites&lt;&#x2F;strong&gt;. Expect around 4kB
(non-compressed) per article.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strike&gt;The &lt;strong&gt;compile times are abysmal&lt;&#x2F;strong&gt; at the moment (around 1.5 minutes after a
fresh install on my machine), mainly because we’re compiling the Rust crate
from scratch every time we rebuild the index.&lt;&#x2F;strike&gt;&lt;br &#x2F;&gt;
Update: This is mostly fixed thanks to the awesome work of
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;CephalonRho&quot;&gt;CephalonRho&lt;&#x2F;a&gt; in PR
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;tinysearch&#x2F;pull&#x2F;13&quot;&gt;#13&lt;&#x2F;a&gt;. Thanks again!&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The final Wasm code is laser-fast because we save the roundtrips to a
search-server. The instant feedback loop feels more like filtering a list than
searching through posts. It can even work fully offline, which might be nice if
you like to bundle it with an app.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Maybe You Don&#x27;t Need Kubernetes</title>
        <published>2019-03-21T00:00:00+00:00</published>
        <updated>2019-03-21T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2019/maybe-you-dont-need-kubernetes/"/>
        <id>https://endler.dev/2019/maybe-you-dont-need-kubernetes/</id>
        
        <content type="html" xml:base="https://endler.dev/2019/maybe-you-dont-need-kubernetes/">&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2019&amp;#x2F;maybe-you-dont-need-kubernetes&amp;#x2F;scooter.svg&quot; 
        
            alt=&quot;A woman riding a scooter&quot;
        

        

        
        
        
            width=&quot;617&quot;
        
        
            height=&quot;347&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            A woman riding a scooter
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: Illustration created by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freepik.com&#x2F;free-photos-vectors&#x2F;car&quot;&gt;freepik&lt;&#x2F;a&gt;, Nomad logo by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;&quot;&gt;HashiCorp&lt;&#x2F;a&gt;.
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Kubernetes is the 800-pound gorilla of container orchestration.&lt;br &#x2F;&gt;
It powers some of the biggest deployments worldwide, but it comes
with a price tag.&lt;&#x2F;p&gt;
&lt;p&gt;Especially for smaller teams, it can be time-consuming to maintain and has a
steep learning curve. For what our team of four wanted to achieve at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tech.trivago.com&quot;&gt;trivago&lt;&#x2F;a&gt;, it
added too much overhead. So we looked into alternatives — and fell in love with
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;&quot;&gt;Nomad&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-wishlist&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-wishlist&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Wishlist&lt;&#x2F;h2&gt;
&lt;p&gt;Our team runs a number of typical services for monitoring and performance
analysis: API endpoints for metrics written in Go, Prometheus exporters, log
parsers like Logstash or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;trivago&#x2F;gollum&quot;&gt;Gollum&lt;&#x2F;a&gt;, and databases like InfluxDB or Elasticsearch.
Each of these services run in their own container. We needed a simple system to
keep those jobs running.&lt;&#x2F;p&gt;
&lt;p&gt;We started with a list of requirements for container orchestration:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Run a fleet of services across many machines.&lt;&#x2F;li&gt;
&lt;li&gt;Provide an overview of running services.&lt;&#x2F;li&gt;
&lt;li&gt;Allow for communication between services.&lt;&#x2F;li&gt;
&lt;li&gt;Restart them automatically when they die.&lt;&#x2F;li&gt;
&lt;li&gt;Be manageable by a small team.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;On top of that, the following things were nice to have but not strictly
required:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Tag machines by their capabilities (e.g., label machines with fast disks for
I&#x2F;O heavy services.)&lt;&#x2F;li&gt;
&lt;li&gt;Be able to run these services independently of any orchestrator (e.g. in
development).&lt;&#x2F;li&gt;
&lt;li&gt;Have a common place to share configurations and secrets.&lt;&#x2F;li&gt;
&lt;li&gt;Provide an endpoint for metrics and logging.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;why-kubernetes-was-not-a-good-fit-for-us&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-kubernetes-was-not-a-good-fit-for-us&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Why Kubernetes Was Not A Good Fit For Us&lt;&#x2F;h2&gt;
&lt;p&gt;When creating a prototype with Kubernetes, we noticed that we started adding
ever-more complex layers of logic to operate our services. Logic on which we
implicitly relied on.&lt;&#x2F;p&gt;
&lt;p&gt;As an example, Kubernetes allows embedding service configurations using
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;configure-pod-container&#x2F;configure-pod-configmap&#x2F;&quot;&gt;ConfigMaps&lt;&#x2F;a&gt;. Especially when merging multiple config files or
adding more services to a pod, this can get quite confusing quickly.
Kubernetes - or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;helm.sh&#x2F;&quot;&gt;helm&lt;&#x2F;a&gt;, for that matter - allows injecting external configs
dynamically to ensure separation of concerns. But this can
lead to tight, implicit coupling between your project and Kubernetes.
Helm and ConfigMaps are optional features so you don’t have to use them. You
might as well just copy the config into the Docker image. However, it’s tempting
to go down that path and build unnecessary abstractions that can later bite you.&lt;&#x2F;p&gt;
&lt;p&gt;On top of that, the Kubernetes ecosystem is still rapidly evolving. It takes a
fair amount of time and energy to stay up-to-date with the best practices and
latest tooling. Kubectl, minikube, kubeadm, helm, tiller, kops, oc - the list
goes on and on. Not all tools are necessary to get started with Kubernetes, but
it’s hard to know which ones are, so you have to be at least aware of them.
Because of that, the learning curve is quite steep.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-to-use-kubernetes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#when-to-use-kubernetes&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;When To Use Kubernetes&lt;&#x2F;h2&gt;
&lt;p&gt;At trivago specifically, many teams use Kubernetes and are quite happy with it.
These instances are managed by Google or Amazon however, which have the capacity to do so.&lt;&#x2F;p&gt;
&lt;p&gt;Kubernetes comes with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jvns.ca&#x2F;blog&#x2F;2017&#x2F;08&#x2F;05&#x2F;how-kubernetes-certificates-work&#x2F;&quot;&gt;amazing
features&lt;&#x2F;a&gt;,
that make container orchestration at scale more manageable:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Fine-grained &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;reference&#x2F;access-authn-authz&#x2F;authorization&#x2F;&quot;&gt;rights management&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;extend-kubernetes&#x2F;api-extension&#x2F;custom-resources&#x2F;#custom-controllers&quot;&gt;Custom controllers&lt;&#x2F;a&gt; allow getting logic into the cluster. These are just
programs that talk to the Kubernetes API.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;tasks&#x2F;run-application&#x2F;horizontal-pod-autoscale&#x2F;&quot;&gt;Autoscaling&lt;&#x2F;a&gt;! Kubernetes can scale your services up and down on demand. It
uses service metrics to do this without manual intervention.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The question is if you really need all those features. You can’t rely on these
abstractions to just work; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jvns.ca&#x2F;blog&#x2F;2017&#x2F;08&#x2F;05&#x2F;how-kubernetes-certificates-work&#x2F;&quot;&gt;you’ll have to learn what’s going on under the
hood&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Especially in our team, which runs most services on-premise (because of its
close connection to trivago’s core infrastructure), we didn’t want to afford
running our own Kubernetes cluster; we wanted to ship services instead.&lt;&#x2F;p&gt;
&lt;figure&gt;
    
        &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;twitter.com&amp;#x2F;QuinnyPig&amp;#x2F;status&amp;#x2F;1093261169614356490&quot;&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2019&amp;#x2F;maybe-you-dont-need-kubernetes&amp;#x2F;nuclear-kubernetes.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2019&amp;#x2F;maybe-you-dont-need-kubernetes&amp;#x2F;nuclear-kubernetes.jpg&quot; 
        
            alt=&quot;Nuclear hot take: nobody will care about Kubernetes in five years. -A tweet by Corey Quinn&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;485&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    
        &lt;&#x2F;a&gt;
    

    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;batteries-not-included&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#batteries-not-included&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Batteries Not Included&lt;&#x2F;h2&gt;
&lt;p&gt;Nomad is the 20% of service orchestration that gets you 80% of the way. All it
does is manage deployments. It takes care of your rollouts and restarts your
containers in case of errors, and that’s about it.&lt;&#x2F;p&gt;
&lt;p&gt;The entire point of Nomad is that it does &lt;em&gt;less&lt;&#x2F;em&gt;: it doesn’t include
fine-grained rights management or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;concepts&#x2F;services-networking&#x2F;network-policies&#x2F;&quot;&gt;advanced network policies&lt;&#x2F;a&gt;, and that’s by
design. Those components are provided as enterprise services, by a third-party
— or not at all.&lt;&#x2F;p&gt;
&lt;p&gt;I think Nomad hit a sweet-spot between ease of use and expressiveness. It’s good
for small, mostly independent services. If you need more control, you’ll have to
build it yourself or use a different approach. Nomad is &lt;em&gt;just&lt;&#x2F;em&gt; an orchestrator.&lt;&#x2F;p&gt;
&lt;p&gt;The best part about Nomad is that it’s easy to &lt;em&gt;replace&lt;&#x2F;em&gt;. There is little to no
vendor lock-in because the functionality it provides can easily be integrated
into any other system that manages services. It just runs as a plain old single
binary on every machine in your cluster; that’s it!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-nomad-ecosystem-of-loosely-coupled-components&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-nomad-ecosystem-of-loosely-coupled-components&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Nomad Ecosystem Of Loosely Coupled Components&lt;&#x2F;h2&gt;
&lt;p&gt;The real power of Nomad lies within its ecosystem. It integrates very well with
other - completely optional - products like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.consul.io&#x2F;&quot;&gt;Consul&lt;&#x2F;a&gt; (a key-value store) or
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.vaultproject.io&#x2F;&quot;&gt;Vault&lt;&#x2F;a&gt; (for secrets handling). Inside your Nomad file, you can have sections
for fetching data from those services:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;template&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  data&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;EOH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;LOG_LEVEL=&amp;quot;{{key &amp;quot;service&#x2F;geo-api&#x2F;log-verbosity&amp;quot;}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-string&quot;&gt;API_KEY=&amp;quot;{{with secret &amp;quot;secret&#x2F;geo-api-key&amp;quot;}}{{.Data.value}}{{end}}&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;EOH&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  destination&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;secrets&#x2F;file.env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  env&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;         =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will read the &lt;code&gt;service&#x2F;geo-api&#x2F;log-verbosity&lt;&#x2F;code&gt; key from Consul and expose it
as a &lt;code&gt;LOG_LEVEL&lt;&#x2F;code&gt; environment variable inside your job. It’s also exposing
&lt;code&gt;secret&#x2F;geo-api-key&lt;&#x2F;code&gt; from Vault as &lt;code&gt;API_KEY&lt;&#x2F;code&gt;. Simple, but powerful!&lt;&#x2F;p&gt;
&lt;p&gt;Because it’s so simple, Nomad can also be easily extended with other services
through its API. For example, jobs can be tagged for service discovery. At
trivago, we tag all services, which expose metrics, with &lt;code&gt;trv-metrics&lt;&#x2F;code&gt;. This
way, Prometheus finds the services via Consul and periodically scrapes the
&lt;code&gt;&#x2F;metrics&lt;&#x2F;code&gt; endpoint for new data. The same can be done for logs by integrating
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grafana.com&#x2F;oss&#x2F;loki&quot;&gt;Loki&lt;&#x2F;a&gt; for example.&lt;&#x2F;p&gt;
&lt;p&gt;There are many other examples for extensibility:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Trigger a Jenkins job using a webhook and Consul watches to redeploy your
Nomad job on service config changes.&lt;&#x2F;li&gt;
&lt;li&gt;Use Ceph to add a distributed file system to Nomad.&lt;&#x2F;li&gt;
&lt;li&gt;Use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fabiolb&#x2F;fabio&quot;&gt;fabio&lt;&#x2F;a&gt; for load balancing.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All of this allowed us to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tech.trivago.com&#x2F;post&#x2F;2019-01-25-nomadourexperiencesandbestpractices&#x2F;&quot;&gt;grow our infrastructure organically&lt;&#x2F;a&gt; without too much
up-front commitment.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fair-warning&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#fair-warning&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Fair Warning&lt;&#x2F;h2&gt;
&lt;p&gt;No system is perfect. I advise you not to use any fancy new features in
production right now. There are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues?q=is%3Aopen+is%3Aissue+label%3Abug&quot;&gt;bugs&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hashicorp&#x2F;nomad&#x2F;issues&#x2F;698&quot;&gt;missing features&lt;&#x2F;a&gt; of course - but
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kubernetes&#x2F;kubernetes&#x2F;issues?q=is%3Aopen+is%3Aissue+label%3Akind%2Fbug&quot;&gt;that’s also the case for
Kubernetes&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Compared to Kubernetes, there is far less momentum behind Nomad. Kubernetes has
seen around 75.000 commits and 2000 contributors so far, while Nomad sports about
14.000 commits and 300 contributors. It will be hard for Nomad to keep up with
the velocity of Kubernetes, but maybe it doesn’t have to! The scope is much more
narrow and the smaller community could also mean that it’ll be easier to get your
pull request accepted, in comparison to Kubernetes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#summary&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;The takeaway is: &lt;strong&gt;don’t use Kubernetes just because everyone else does&lt;&#x2F;strong&gt;.
Carefully evaluate your requirements and check which tool fits the bill.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re planning to deploy a fleet of homogenous services on large-scale
infrastructure, Kubernetes might be the way to go. Just be aware of the
additional &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ka_szczepanski&#x2F;status&#x2F;1394296607806525440&quot;&gt;complexity and operational costs&lt;&#x2F;a&gt;. Some of these costs can be
avoided by using a managed Kubernetes environment like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;kubernetes-engine&#x2F;&quot;&gt;Google Kubernetes
Engine&lt;&#x2F;a&gt; or &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;eks&#x2F;&quot;&gt;Amazon EKS&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re just looking for a reliable orchestrator that is easy to maintain and
extendable, why not give &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.nomadproject.io&#x2F;&quot;&gt;Nomad&lt;&#x2F;a&gt; a try? You might be surprised by how far it’ll get you.&lt;&#x2F;p&gt;
&lt;p&gt;If Kubernetes were a car, Nomad would be a scooter. Sometimes you prefer one and
sometimes the other. Both have their right to exist.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>What Is Rust Doing Behind the Curtains?</title>
        <published>2018-12-02T00:00:00+00:00</published>
        <updated>2018-12-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/cargo-inspect/"/>
        <id>https://endler.dev/2018/cargo-inspect/</id>
        
        <summary type="html">&lt;p&gt;Rust allows for a lot of syntactic sugar, that makes it a pleasure to write. It is sometimes hard, however, to look behind the curtain and see what the compiler is really doing with our code.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>The Unreasonable Effectiveness of Excel Macros</title>
        <published>2018-11-05T00:00:00+00:00</published>
        <updated>2018-11-05T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/excel/"/>
        <id>https://endler.dev/2018/excel/</id>
        
        <summary type="html">&lt;p&gt;I never was a big fan of internships, partially because all the exciting
companies were far away from my little village in Bavaria and partially because
I was too shy to apply.&lt;&#x2F;p&gt;
&lt;p&gt;Only once I applied for an internship in Ireland as part of a school program.
Our teacher assigned the jobs and so my friend got one at Apple and I ended up
at a medium-sized IT distributor — let’s call them PcGo.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Switching from a German to a US Keyboard Layout - Is It Worth It?</title>
        <published>2018-09-02T00:00:00+00:00</published>
        <updated>2025-04-24T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/keyboard/"/>
        <id>https://endler.dev/2018/keyboard/</id>
        
        <content type="html" xml:base="https://endler.dev/2018/keyboard/">&lt;p&gt;For the first three decades of my life, I’ve exclusively used a German keyboard layout for programming. In 2018, I finally switched to a US layout.
This post summarizes my thoughts around the topic.
I was looking for a similar article before jumping the gun, but I couldn’t find one — so I wrote it.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;keyboard&amp;#x2F;keychron.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;keyboard&amp;#x2F;keychron.jpg&quot; 
        
            alt=&quot;My current keyboard (as of April 2021), the low-profile, tenkeyless Keychron K1 is close to my favorite input device. Yes, I got the RGB version. &amp;amp;mdash; [Amazon referral link](https:&amp;#x2F;&amp;#x2F;amzn.to&amp;#x2F;3tRatjU).&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;352&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            My current keyboard (as of April 2021), the low-profile, tenkeyless Keychron K1 is close to my favorite input device. Yes, I got the RGB version. — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;3tRatjU&quot;&gt;Amazon referral link&lt;&#x2F;a&gt;.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;why-switch-to-the-us-layout&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-switch-to-the-us-layout&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Why Switch To the US Layout?&lt;&#x2F;h2&gt;
&lt;p&gt;I was reasonably efficient when writing prose, but felt like
a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.etsy.com&#x2F;listing&#x2F;896826954&#x2F;funny-piano-art-print-leptodactylous-aye&quot;&gt;lemur on a piano&lt;&#x2F;a&gt; when programming:
lots of finger-stretching while trying to reach the special keys like &lt;code&gt;{&lt;&#x2F;code&gt;, &lt;code&gt;;&lt;&#x2F;code&gt;, or &lt;code&gt;&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;keyboard&amp;#x2F;KB_Germany.svg&quot; 
        
            alt=&quot;German Keyboard Layout&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;217&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            German Keyboard Layout
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;w&#x2F;index.php?curid=1058095&quot;&gt;Image by Wikipedia&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Here’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;German_keyboard_layout&quot;&gt;Wikipedia’s polite
explanation&lt;&#x2F;a&gt; why the
German keyboard &lt;strong&gt;sucks for programming&lt;&#x2F;strong&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Like many other non-American keyboards, German keyboards change the right Alt
key into an &lt;b&gt;Alt Gr key to access a third level&lt;&#x2F;b&gt; of key assignments. This is
necessary because the umlauts and some other special characters leave no room
to have all the special symbols of ASCII, needed by programmers among others,
available on the first or second (shifted) levels without unduly increasing
the size of the keyboard.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;but-why-switch-now&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#but-why-switch-now&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;But Why Switch &lt;strong&gt;Now&lt;&#x2F;strong&gt;?&lt;&#x2F;h2&gt;
&lt;p&gt;After many years of using a rubber-dome &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;support.logitech.com&#x2F;en_us&#x2F;product&#x2F;cordless-desktop-wave&#x2F;&quot;&gt;Logitech Cordless Desktop
Wave&lt;&#x2F;a&gt;, I
had to get a mechanical keyboard again.&lt;&#x2F;p&gt;
&lt;p&gt;Those rubber domes just feel too mushy to me now. In addition to that, I enjoy the
clicky sound of a mechanical keyboard and the noticeable tactile bump. (I’m using
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;3mm2WHf&quot;&gt;Cherry MX Brown Keys&lt;&#x2F;a&gt; with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;amzn.to&#x2F;3miCfTK&quot;&gt;O-Ring dampeners&lt;&#x2F;a&gt; to contain the anger of my coworkers.)&lt;&#x2F;p&gt;
&lt;p&gt;Most mechanical keyboards come with an ANSI US layout only, so I figured, I’d
finally make the switch.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;keyboard&amp;#x2F;durgod_taurus.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;keyboard&amp;#x2F;durgod_taurus.jpg&quot; 
        
            alt=&quot;My first mechanical keyboard &amp;amp;mdash; [Durgod Taurus K320](https:&amp;#x2F;&amp;#x2F;www.amazon.de&amp;#x2F;gp&amp;#x2F;product&amp;#x2F;B07QK16RDQ&amp;#x2F;ref=as_li_tl?ie=UTF8&amp;amp;tag=matthiasendle-21&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;linkCode=as2&amp;amp;creativeASIN=B07QK16RDQ&amp;amp;linkId=fb0a782ecbc713f8266b90b941375a5f) (referral link). They also have a fancy [white-pink](https:&amp;#x2F;&amp;#x2F;www.amazon.de&amp;#x2F;gp&amp;#x2F;product&amp;#x2F;B081LZV2QM?ie=UTF8&amp;amp;tag=matthiasendle-21&amp;amp;camp=1638&amp;amp;linkCode=xm2&amp;amp;creativeASIN=B081LZV2QM) ISO version now.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;278&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            My first mechanical keyboard — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.de&#x2F;gp&#x2F;product&#x2F;B07QK16RDQ&#x2F;ref=as_li_tl?ie=UTF8&amp;amp;tag=matthiasendle-21&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;linkCode=as2&amp;amp;creativeASIN=B07QK16RDQ&amp;amp;linkId=fb0a782ecbc713f8266b90b941375a5f&quot;&gt;Durgod Taurus K320&lt;&#x2F;a&gt; (referral link). They also have a fancy &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.de&#x2F;gp&#x2F;product&#x2F;B081LZV2QM?ie=UTF8&amp;amp;tag=matthiasendle-21&amp;amp;camp=1638&amp;amp;linkCode=xm2&amp;amp;creativeASIN=B081LZV2QM&quot;&gt;white-pink&lt;&#x2F;a&gt; ISO version now.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;how-long-did-it-take-to-get-accustomed-to-the-new-layout&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#how-long-did-it-take-to-get-accustomed-to-the-new-layout&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;How Long Did It Take To Get Accustomed To The New Layout?&lt;&#x2F;h2&gt;
&lt;p&gt;Working as a Software Engineer, my biggest fear was, that the switch would slow
down my daily work. This turned out not to be true. I was reasonably productive
&lt;strong&gt;from day one&lt;&#x2F;strong&gt;, and nobody even noticed any difference. (That’s a good thing,
&lt;em&gt;right&lt;&#x2F;em&gt;?)&lt;&#x2F;p&gt;
&lt;p&gt;At first, I didn’t like the &lt;em&gt;bar-shaped US-Return key&lt;&#x2F;em&gt;. I preferred the European
layout with a &lt;em&gt;vertical enter key&lt;&#x2F;em&gt;. I was afraid that I would hit the key by
accident. After a while, I find that the US return key to be even more convenient.
I never hit it by accident, and it’s easy to reach with my pinky from the home position.&lt;&#x2F;p&gt;
&lt;p&gt;Within two weeks, I was back to 100% typing speed.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;did-my-programming-speed-improve-noticeably&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#did-my-programming-speed-improve-noticeably&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Did My Programming Speed Improve Noticeably?&lt;&#x2F;h2&gt;
&lt;p&gt;Yup. I’d say I can type programs about 30% faster.&lt;&#x2F;p&gt;
&lt;p&gt;Especially when using special characters (&lt;code&gt;&#x2F;&lt;&#x2F;code&gt;, &lt;code&gt;;&lt;&#x2F;code&gt;, &lt;code&gt;{&lt;&#x2F;code&gt;, and so on) I’m much
faster now; partly because the key locations feel more intuitive, but mainly
because my fingers stay at their dedicated positions.&lt;&#x2F;p&gt;
&lt;p&gt;Somehow the position of special characters feels &lt;em&gt;just right&lt;&#x2F;em&gt;. I can finally understand the
reason why Vim is using &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; for search or why the pipe symbol is &lt;code&gt;|&lt;&#x2F;code&gt;: both are
easy to reach! &lt;a href=&quot;&#x2F;2018&#x2F;ten-years-of-vim&quot;&gt;It all makes sense!&lt;&#x2F;a&gt;
(For a fun time, try that on a German keyboard!)&lt;&#x2F;p&gt;
&lt;p&gt;I understand why Mircosoft chose &lt;code&gt;\&lt;&#x2F;code&gt; as a directory separator: it’s easily
accessible from a US keyboard. On the German layout, it’s… just… awful
(&lt;code&gt;Alt Gr&lt;&#x2F;code&gt;+&lt;code&gt;ß&lt;&#x2F;code&gt; on Windows, &lt;code&gt;Shift&lt;&#x2F;code&gt; + &lt;code&gt;Option&lt;&#x2F;code&gt; + &lt;code&gt;7&lt;&#x2F;code&gt; on Mac).&lt;&#x2F;p&gt;
&lt;p&gt;The opening curly brace on a German layout Mac is produced with &lt;code&gt;Alt&lt;&#x2F;code&gt;+&lt;code&gt;8&lt;&#x2F;code&gt;, which
always made me leave the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Touch_typing#Home_row&quot;&gt;home
row&lt;&#x2F;a&gt; and break my typing
flow. Now there are dedicated keys for parentheses. Such a relief!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;em&gt;Update:&lt;&#x2F;em&gt; It also helps greatly when looking up hotkeys for IDEs, text editors,
photo editors, etc. because some programs remap shortcuts for the German market,
which means that all the English documentation is totally worthless.
Thanks to the English layout, I can just use the shortcuts mentioned and move on with my life.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;am-i-slower-when-writing-german-texts-now&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#am-i-slower-when-writing-german-texts-now&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Am I Slower When Writing German Texts Now?&lt;&#x2F;h2&gt;
&lt;p&gt;In the beginning, I was.&lt;&#x2F;p&gt;
&lt;p&gt;Somehow my brain associated the German layout with German
texts. First, I used the macOS layout switcher.
This turned out to be cumbersome and take time.&lt;&#x2F;p&gt;
&lt;p&gt;Then I found the “&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hci.rwth-aachen.de&#x2F;usgermankeyboard&quot;&gt;US with Umlauts via Option Key
Layout&lt;&#x2F;a&gt;”. It works perfectly fine for
me. It allows me to use a single Keyboard layout but insert German umlauts at will
(e.g. ö is &lt;code&gt;Option&lt;&#x2F;code&gt;+&lt;code&gt;o&lt;&#x2F;code&gt;). There is probably a similar layout for other language combinations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stefanimhoff.de&#x2F;&quot;&gt;Stefan Imhoff&lt;&#x2F;a&gt; notified me that there’s also a
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.stefanimhoff.de&#x2F;&quot;&gt;Karabiner&lt;&#x2F;a&gt; rule which does the same. Might come
in handy in case you already use this tool.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;is-switching-between-keyboards-painful&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#is-switching-between-keyboards-painful&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Is Switching Between Keyboards Painful?&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;keyboard&amp;#x2F;KB_United_States.svg&quot; 
        
            alt=&quot;US keyboard layout&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;216&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            US keyboard layout
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;commons.wikimedia.org&#x2F;wiki&#x2F;File:KB_United_States.svg&quot;&gt;Wikipedia&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;My built-in MacBook Pro keyboard layout is still German. I was afraid, that switching between
the internal German and the external English keyboard would confuse me. This
turned out not to be a problem. I rarely look at the print anyway.
(Update: can’t remember when I last looked at the print.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-often-do-you-switch-back-to-a-german-layout-now&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#how-often-do-you-switch-back-to-a-german-layout-now&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;How Often Do You Switch Back To A German Layout Now?&lt;&#x2F;h2&gt;
&lt;p&gt;Never. My Girlfriend has a German keyboard and every time I have to use it, I switch to the US layout. It makes her very happy when I do this and forget to switch back to German when I’m done.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#summary&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;If you consider switching, just do it! I don’t look back at all
and apart from the initial transition period, I still couldn’t find any downsides.&lt;&#x2F;p&gt;
&lt;p&gt;Since posting this article, many of my friends made the switch as well and
had similar experiences:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;wolfgang.gassler.org&#x2F;switch-keyboard-german-to-english-linux-fedora&#x2F;&quot;&gt;Wolfgang Gassler wrote a post about his layout switch on Linux&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;ro14nd&#x2F;status&#x2F;1304360915840753664&quot;&gt;Discussion of the article on Twitter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>fastcat - A Faster `cat` Implementation Using Splice</title>
        <published>2018-07-31T00:00:00+00:00</published>
        <updated>2023-01-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/fastcat/"/>
        <id>https://endler.dev/2018/fastcat/</id>
        
        <content type="html" xml:base="https://endler.dev/2018/fastcat/">&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;fastcat&amp;#x2F;fastcat.svg&quot; 
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;270&quot;
         
    &#x2F;&gt;
    

    

    
&lt;&#x2F;figure&gt;
&lt;p&gt;Lots of people asked me to write another piece about the internals of well-known
Unix commands. Well, actually, nobody asked, but it makes for a good
intro. I’m sure you’ve read the previous parts about &lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;yes&#x2F;&quot;&gt;&lt;code&gt;yes&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2018&#x2F;ls&#x2F;&quot;&gt;&lt;code&gt;ls&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; — they are epic.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, today we talk about &lt;code&gt;cat&lt;&#x2F;code&gt;, which is used to concatenate files - or, more
commonly, abused to print a file’s contents to the screen.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Concatenate files, the intended purpose&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; input1.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; input2.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; input3.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; output.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Print file to screen, the most common use-case&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; myfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;implementing-cat&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#implementing-cat&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Implementing cat&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s a naive &lt;code&gt;cat&lt;&#x2F;code&gt; in Ruby:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;!&#x2F;usr&#x2F;bin&#x2F;env ruby&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;each&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; do&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-class&quot;&gt;    IO&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;foreach&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;arg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; do&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;line&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;      puts&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-other z-constant&quot;&gt;ARGV&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This program goes through each file and prints its contents line by line.
Easy peasy! But wait, how fast is this tool?&lt;&#x2F;p&gt;
&lt;p&gt;I quickly created a random 2 GB file for the benchmark.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s compare the speed of our naive implementation with the system one
using the awesome &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.ivarch.com&#x2F;programs&#x2F;pv.shtml&quot;&gt;pv&lt;&#x2F;a&gt; (Pipe Viewer) tool.
All tests are averaged over five runs on a warm cache (file in memory).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Ruby 2.5.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; .&#x2F;rubycat myfile | pv -r &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[196MiB&#x2F;s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Not bad, I guess? How does it compare with my system’s cat?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cat myfile | pv -r &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[1.90GiB&#x2F;s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Uh oh, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git.savannah.gnu.org&#x2F;gitweb&#x2F;?p=coreutils.git;a=blob;f=src&#x2F;cat.c;h=3c319511c767f65d2e420b3bff8fa6197ddbb37b;hb=HEAD&quot;&gt;GNU cat&lt;&#x2F;a&gt; is &lt;strong&gt;ten times faster&lt;&#x2F;strong&gt; than our little Ruby cat. 💎🐈🐌&lt;&#x2F;p&gt;
&lt;h2 id=&quot;making-our-ruby-cat-a-little-faster&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#making-our-ruby-cat-a-little-faster&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Making our Ruby cat a little faster&lt;&#x2F;h2&gt;
&lt;p&gt;Our naive Ruby code can be tweaked a bit.
Turns out line buffering hurts performance in the end&lt;sup&gt;&lt;a href=&quot;#fn1&quot; id=&quot;ref1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;!&#x2F;usr&#x2F;bin&#x2F;env ruby&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;each&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; do&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-class&quot;&gt;    IO&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;copy_stream&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;arg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-other z-constant&quot;&gt; STDOUT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-other z-constant&quot;&gt;ARGV&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rubycat myfile | pv -r &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[1.81GiB&#x2F;s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Wow… we didn’t really try hard, and we’re already approaching the speed of a
tool that gets optimized &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Cat_(Unix)&quot;&gt;since
1971&lt;&#x2F;a&gt;. 🎉&lt;&#x2F;p&gt;
&lt;p&gt;But before we celebrate too much, let’s see if we can go even faster.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;splice&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#splice&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Splice&lt;&#x2F;h2&gt;
&lt;p&gt;What initially motivated me to write about &lt;code&gt;cat&lt;&#x2F;code&gt; was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=15455897&quot;&gt;this comment by user
wahern on
Hacker News&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I’m surprised that neither GNU yes nor GNU cat uses splice(2).&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Could this &lt;em&gt;splice&lt;&#x2F;em&gt; thing make printing files even faster? — I was intrigued.&lt;&#x2F;p&gt;
&lt;p&gt;Splice was first introduced to the Linux Kernel in 2006, and there is a nice
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20130305002825&#x2F;https:&#x2F;&#x2F;kerneltrap.org&#x2F;node&#x2F;6505&quot;&gt;summary from Linus Torvalds himself&lt;&#x2F;a&gt;,
but I prefer the description from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;2&#x2F;splice&quot;&gt;manpage&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;splice()&lt;&#x2F;strong&gt; moves data between two file descriptors without copying
between kernel address space and user address space. It transfers up
to &lt;code&gt;len&lt;&#x2F;code&gt; bytes of data from the file descriptor &lt;code&gt;fd_in&lt;&#x2F;code&gt; to the file
descriptor &lt;code&gt;fd_out&lt;&#x2F;code&gt;, where one of the file descriptors must refer to a
pipe.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;If you really want to dig deeper, here’s the corresponding &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;torvalds&#x2F;linux&#x2F;blob&#x2F;6ed0529fef09f50ef41d396cb55c5519e4936b16&#x2F;fs&#x2F;splice.c&quot;&gt;source code from the
Linux Kernel&lt;&#x2F;a&gt;,
but we don’t need to know all the nitty-gritty details for now.
Instead, we can just inspect the header from the C implementation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-keyword z-control&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-directive z-include z-keyword z-control&quot;&gt;include&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fcntl.h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;ssize_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; splice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-built-in z-primitive z-storage z-type&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fd_in&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-type&quot;&gt; loff_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;off_in&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-built-in z-primitive z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fd_out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type&quot;&gt;                loff_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;off_out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; size_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-built-in z-primitive z-storage z-type&quot;&gt;                unsigned&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-built-in z-primitive z-storage z-type&quot;&gt; int&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; flags&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To break it down even more, here’s how we would copy the entire &lt;code&gt;src&lt;&#x2F;code&gt; file to &lt;code&gt;dst&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; ssize_t&lt;&#x2F;span&gt;&lt;span&gt; r &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; splice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; dst&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; NULL&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The cool thing about this is that all of it happens inside the Linux kernel, which means we won’t copy a single byte to userspace (where our program runs).
Ideally, splice works by remapping pages and does not actually copy
any data, which may improve I&#x2F;O performance
(&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Splice_(system_call)&quot;&gt;reference&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;fastcat&amp;#x2F;buffers.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;fastcat&amp;#x2F;buffers.jpg&quot; 
        
            alt=&quot;File icon by Aleksandr Vector from the Noun Project. Terminal icon by useiconic.com from the Noun Project.&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;488&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: File icon by Aleksandr Vector from the Noun Project. Terminal icon by useiconic.com from the Noun Project.
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;using-splice-from-rust&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#using-splice-from-rust&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Using splice from Rust&lt;&#x2F;h2&gt;
&lt;p&gt;I have to say I’m not a C programmer and I prefer Rust because it offers a safer
interface. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nix-rust&#x2F;nix&#x2F;blob&#x2F;ebf75050f2f2726808308f76253f27c97aa6db15&#x2F;src&#x2F;fcntl.rs#L320-L329&quot;&gt;Here’s the same thing in Rust&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;cfg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;any&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;target_os &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;linux&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; target_os &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;android&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; splice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    fd_in&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; RawFd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    off_in&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;loff_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    fd_out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; RawFd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    off_out&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;loff_t&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    len&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    flags&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; SpliceFFlags&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now, I didn’t implement the Linux bindings myself. Instead, I just used a library called
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nix-rust&#x2F;nix&quot;&gt;nix&lt;&#x2F;a&gt;, which provides Rust friendly bindings to *nix APIs.&lt;&#x2F;p&gt;
&lt;p&gt;There is one caveat, though:
We cannot really copy the file directly to standard out, because splice
requires one file descriptor to be a pipe.
The way around that is to create a pipe, which consists of a reader and a
writer (&lt;code&gt;rd&lt;&#x2F;code&gt; and &lt;code&gt;wr&lt;&#x2F;code&gt;).
We pipe the file into the writer, and then we read from the pipe and push the data to stdout.&lt;&#x2F;p&gt;
&lt;p&gt;You can see that I use a relatively big buffer of 16384 bytes (2&lt;sup&gt;14&lt;&#x2F;sup&gt;) to improve performance.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; nix&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;File&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;os&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;unix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;AsRawFd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; nix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fcntl&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;splice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; SpliceFFlags&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; nix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;unistd&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;pipe&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; BUF_SIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 16384&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;skip&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; File&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;open&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;expect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;format!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;fcat: &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;: No such file or directory&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;rd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; wr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; pipe&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;        loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; splice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                input&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;as_raw_fd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                None&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                wr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                None&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;                BUF_SIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;                SpliceFFlags&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;empty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; We read 0 bytes from the input,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; which means we&amp;#39;re done copying.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;                break&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;            let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _res&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; splice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                rd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                None&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;as_raw_fd&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;                None&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;                BUF_SIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;                SpliceFFlags&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;empty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            )&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So, how fast is this?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fcat myfile | pv -r &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[5.90GiB&#x2F;s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Holy guacamole. That’s &lt;strong&gt;over three times as fast as system cat&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;operating-system-support&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#operating-system-support&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Operating System support&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Linux&lt;&#x2F;strong&gt; and &lt;strong&gt;Android&lt;&#x2F;strong&gt; are fully supported.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;12230316&#x2F;do-other-operating-systems-implement-the-linux-system-call-splice?lq=1&quot;&gt;OpenBSD&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;
also has some sort of splice implementation called
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;man.openbsd.org&#x2F;sosplice&quot;&gt;&lt;code&gt;sosplice&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. I didn’t test that, though.&lt;&#x2F;li&gt;
&lt;li&gt;On &lt;strong&gt;macOS&lt;&#x2F;strong&gt;, the closest thing to splice is its bigger brother,
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.unix.com&#x2F;man-page&#x2F;osx&#x2F;2&#x2F;sendfile&#x2F;&quot;&gt;sendfile&lt;&#x2F;a&gt;, which can send a
file to a socket within the Kernel. Unfortunately, it does not support sending
from file to file.&lt;sup&gt;&lt;a href=&quot;#fn2&quot; id=&quot;ref2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt; There’s also
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20180401103335&#x2F;https:&#x2F;&#x2F;developer.apple.com&#x2F;legacy&#x2F;library&#x2F;documentation&#x2F;Darwin&#x2F;Reference&#x2F;ManPages&#x2F;man3&#x2F;copyfile.3.html&quot;&gt;&lt;code&gt;copyfile&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;,
which has a similar interface, but unfortunately, it is not zero-copy. (I
thought so in the beginning, but &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;libc&#x2F;pull&#x2F;886&quot;&gt;I was
wrong&lt;&#x2F;a&gt;.)&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Windows&lt;&#x2F;strong&gt; doesn’t provide zero-copy file-to-file transfer
(only file-to-socket transfer using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.microsoft.com&#x2F;en-us&#x2F;windows&#x2F;win32&#x2F;api&#x2F;mswsock&#x2F;nf-mswsock-transmitfile&quot;&gt;TransmitFile API&lt;&#x2F;a&gt;).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Nevertheless, in a production-grade
implementation, the splice support could be activated on systems that support
it, while using a generic implementation as a fallback.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nice-but-why-on-earth-would-i-want-that&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#nice-but-why-on-earth-would-i-want-that&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Nice, but why on earth would I want that?&lt;&#x2F;h2&gt;
&lt;p&gt;I have no idea. Probably you don’t, because your bottleneck is somewhere else.
That said, many people use &lt;code&gt;cat&lt;&#x2F;code&gt; for piping data into another process like&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Count all lines in C files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.c&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; wc&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;or&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cat&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; kittens.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; grep&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;dog&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this case, if you notice that &lt;code&gt;cat&lt;&#x2F;code&gt; is the bottleneck try &lt;code&gt;fcat&lt;&#x2F;code&gt; (but first,
&lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;porkmail.org&#x2F;era&#x2F;unix&#x2F;award.html&quot;&gt;try to avoid &lt;code&gt;cat&lt;&#x2F;code&gt; altogether&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;
&lt;p&gt;With some more work, &lt;code&gt;fcat&lt;&#x2F;code&gt; could also be used to directly route packets from one
network card to another, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nc110.sourceforge.io&#x2F;&quot;&gt;similar to netcat&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lessons-learned&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#lessons-learned&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Lessons learned&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;The closer we get to bare metal, the more our hard-won abstractions fall
apart, and we are back to low-level systems programming.&lt;&#x2F;li&gt;
&lt;li&gt;Apart from a fast cat, there’s also a use-case for a slow cat: old computers.
For that purpose, there’s — you guessed it — &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;grox.net&#x2F;software&#x2F;mine&#x2F;slowcat&#x2F;&quot;&gt;slowcat&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That said, I still have no idea why GNU cat does not use splice on Linux. 🤔
The &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;fcat&quot;&gt;source code for fcat is on Github&lt;&#x2F;a&gt;.
Contributions welcome!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#footnotes&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Footnotes&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;sup id=&quot;fn1&quot;&gt;1. Thanks to reader &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;93fbrj&#x2F;fascat_a_faster_cat_implementation_using_splice&#x2F;e3d2chn&#x2F;&quot;&gt;Freeky&lt;&#x2F;a&gt; for making this code more idiomatic.&lt;a href=&quot;#ref1&quot; title=&quot;Jump back to footnote 1 in the text.&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;br &#x2F;&gt;
&lt;sup id=&quot;fn2&quot;&gt;2. Thanks to reader &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;93fbrj&#x2F;fascat_a_faster_cat_implementation_using_splice&#x2F;e3cu3rk&#x2F;&quot;&gt;masklinn&lt;&#x2F;a&gt; for the hint.&lt;a href=&quot;#ref2&quot; title=&quot;Jump back to footnote 2 in the text.&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>That Octocat on the Wall</title>
        <published>2018-06-09T00:00:00+00:00</published>
        <updated>2018-06-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/github/"/>
        <id>https://endler.dev/2018/github/</id>
        
        <content type="html" xml:base="https://endler.dev/2018/github/">&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;github&amp;#x2F;octocat.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2018&amp;#x2F;github&amp;#x2F;octocat.jpg&quot; 
        
            alt=&quot;Photo of my office with Github&amp;#x27;s octocat on the wall over my couch&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;433&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Photo of my office with Github’s octocat on the wall over my couch
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;So I’m in a bit of a sentimental mood lately.
Github got acquired by Microsoft.
While I think the acquisition was well-deserved, I still wish it didn’t happen.
Let me explain.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-early-days&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#my-early-days&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;My early days&lt;&#x2F;h2&gt;
&lt;p&gt;I joined Github on 3rd of January 2010.
Since I was a bit late to the game, my usual handle (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;&quot;&gt;mre&lt;&#x2F;a&gt;) was already taken.
So I naively sent a mail to Github, asking if I could bag the name as it seemed to be abandoned.
To my surprise, I got an answer.
The response came from a guy named &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;defunkt&quot;&gt;Chris Wanstrath&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;All he wrote was “it’s yours.”&lt;&#x2F;p&gt;
&lt;p&gt;That was the moment I fell in love with Github.
I felt encouraged to collaborate on projects, that everybody could contribute something valuable.
Only later I found out that Chris was one of the founders and the CEO of the company.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;living-on-github&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#living-on-github&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Living on Github&lt;&#x2F;h2&gt;
&lt;p&gt;Before Github, there was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;sourceforge.net&#x2F;&quot;&gt;SourceForge&lt;&#x2F;a&gt;, and I only went there to download binaries.
Github showed me, that there was an entire community of like-minded people
out there, who ❤️ to work on code in their free-time.
To me, Github is much more than a git interface; it’s a social network.
While other people browse Facebook or Instagram, I browse Github.&lt;&#x2F;p&gt;
&lt;p&gt;I can still vividly remember getting my &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;Creamy&#x2F;stargazers&quot;&gt;first star&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;Creamy&#x2F;issues&#x2F;1&quot;&gt;my first issue on one of my projects&lt;&#x2F;a&gt; coming from a real (!) person other than myself.&lt;&#x2F;p&gt;
&lt;p&gt;After so many years, a pull-request still feels like the most personal gift anyone could give to me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;github-the-culture&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#github-the-culture&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Github - the culture&lt;&#x2F;h2&gt;
&lt;p&gt;After a while, I started to admire some Github employees deeply:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zachholman.com&#x2F;&quot;&gt;Zach Holman&lt;&#x2F;a&gt; (who is about my age) is a great &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zachholman.com&#x2F;talk&#x2F;utc-is-enough-for-everyone-right&quot;&gt;writer&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=YVb2GsJHejo&quot;&gt;speaker&lt;&#x2F;a&gt;, and one of the most &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;holman&#x2F;spark&quot;&gt;creative developers&lt;&#x2F;a&gt; I can think of.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;scottchacon.com&#x2F;about.html&quot;&gt;Scott Chacon&lt;&#x2F;a&gt;, who &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;de&#x2F;v2&quot;&gt;taught me a lot about git&lt;&#x2F;a&gt; and whose presentation tool, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;puppetlabs&#x2F;showoff&quot;&gt;showoff&lt;&#x2F;a&gt;, I’ve &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;Talks&#x2F;tree&#x2F;master&#x2F;cuda&#x2F;Presentation&quot;&gt;used at University&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mojombo&quot;&gt;Tom Preston-Werner&lt;&#x2F;a&gt;, who I admire for refusing an offer from Microsoft to pursue his dream and build Github, for establishing a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wired.com&#x2F;2013&#x2F;09&#x2F;github-office&#x2F;&quot;&gt;super-nerdy company culture&lt;&#x2F;a&gt;, and for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jekyllrb.com&#x2F;&quot;&gt;Jekyll&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All three developers have since left the company.
I can’t help but notice that Github has changed.
The harassment accusations and letting Zach Holman go are only part of the story.&lt;&#x2F;p&gt;
&lt;p&gt;It has become a company like any other, maintaining a mature product.
It doesn’t &lt;em&gt;excite&lt;&#x2F;em&gt; me anymore.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;an-alternative-reality&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#an-alternative-reality&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;An alternative reality&lt;&#x2F;h2&gt;
&lt;p&gt;There’s still a bitter taste in my mouth when I think that Github has fallen prey to one of the tech giants. I loved Github while it was a small, friendly community of passionate developers.
Could this have been sustainable?&lt;&#x2F;p&gt;
&lt;p&gt;Maybe through paid features for project maintainers.&lt;&#x2F;p&gt;
&lt;p&gt;You see, if you do Open Source every day, it can be a lot of work.
People start depending on your projects, and you feel responsible for keeping the lights on.&lt;&#x2F;p&gt;
&lt;p&gt;To ease the burden, I’d love to have deeper insights into my project usage: visitor statistics for longer than two weeks,
a front page where you could filter and search for events, a better way to handle discussions
(&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nikolas.github.io&#x2F;github-drama&#x2F;&quot;&gt;which can get out of hand quickly&lt;&#x2F;a&gt;), better &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;topics&#x2F;autodevops&#x2F;&quot;&gt;CI integration à la Gitlab&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;These features would be targeted at the top 10% of Github users, a group of 3 million people.
Would this be enough to pay the bills? Probably. Would it be enough to grow? Probably not.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;so-what&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#so-what&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;So what?&lt;&#x2F;h2&gt;
&lt;p&gt;I don’t think the acquisition will kill the culture. Microsoft is a strong partner and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nat.github.io&#x2F;hello&#x2F;&quot;&gt;Nat Friedman&lt;&#x2F;a&gt; is one of us.
On the other side, I’m not as enthusiastic as I used to be.
There’s room for competitors now and I’m beginning to wonder what will be the next Github.
That said, I will keep the Octocat on my office wall, in the hope that the excitement comes back.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Ten Years of Vim</title>
        <published>2018-05-20T00:00:00+00:00</published>
        <updated>2021-04-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/ten-years-of-vim/"/>
        <id>https://endler.dev/2018/ten-years-of-vim/</id>
        
        <content type="html" xml:base="https://endler.dev/2018/ten-years-of-vim/">&lt;div class=&quot;vim&quot;&gt;
&lt;div class=&quot;cursor&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;
&lt;p&gt;When I opened Vim by accident for the first time, I thought it was broken. My
keystrokes changed the screen in unpredictable ways, and I wanted to undo things
and quit. Needless to say, it was an unpleasant experience. There was something
about it though, that kept me coming back and it became my main editor.&lt;&#x2F;p&gt;
&lt;p&gt;Fast forward ten years (!) and I still use Vim.
After all the Textmates and Atoms and PhpStorms I tried, I still find myself at home in Vim.
People keep asking me: Why is that?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-vim&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-vim&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Why Vim?&lt;&#x2F;h2&gt;
&lt;p&gt;Before Vim, I had used many other editors like notepad or nano. They all behaved more or less as expected: you insert text, you move your cursor with the arrow keys or your mouse, and you save with &lt;code&gt;Control + S&lt;&#x2F;code&gt; or by using the menu bar. VI (and Vim, its spiritual successor) is different.&lt;&#x2F;p&gt;
&lt;p&gt;EVERYTHING in Vim is different, and that’s why it’s so highly effective. Let me explain.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-zen-of-vim&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-zen-of-vim&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;The Zen of Vim&lt;&#x2F;h2&gt;
&lt;p&gt;The philosophy behind Vim takes a while to sink in:
While other editors focus on &lt;em&gt;writing&lt;&#x2F;em&gt; as the central part of working with text, Vim thinks it’s &lt;em&gt;editing&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You see, most of the time I don’t spend writing &lt;em&gt;new&lt;&#x2F;em&gt; text; instead, I edit &lt;em&gt;existing&lt;&#x2F;em&gt; text.&lt;br &#x2F;&gt;
I mold text, form it, turn it upside down.
Writing text is craftsmanship and hard work. You have to shape your thoughts with your cold, bare hands until they somewhat form a coherent whole.
This painful process is what Vim tries to make at least bearable. It helps you keep control.
It does that, by providing you sharp, effective tools to modify text.
The core of Vim is a language for editing text.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vim-the-language&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#vim-the-language&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Vim, The Language&lt;&#x2F;h2&gt;
&lt;p&gt;The Vim commands are not cryptic, you already know them.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;To &lt;u&gt;u&lt;&#x2F;u&gt;ndo, type &lt;code&gt;u&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;To &lt;u&gt;f&lt;&#x2F;u&gt;ind the next &lt;u&gt;t&lt;&#x2F;u&gt;, type &lt;code&gt;ft&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;To &lt;u&gt;d&lt;&#x2F;u&gt;elete &lt;u&gt;a&lt;&#x2F;u&gt; &lt;u&gt;w&lt;&#x2F;u&gt;ord, type &lt;code&gt;daw&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;To &lt;u&gt;c&lt;&#x2F;u&gt;hange &lt;u&gt;a&lt;&#x2F;u&gt; &lt;u&gt;s&lt;&#x2F;u&gt;entence, type &lt;code&gt;cas&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;More often than not, you can &lt;em&gt;guess&lt;&#x2F;em&gt; the correct command by thinking of an operation you want to execute and an object to execute it on.
Then just take the first character of every word. Try it!
If anything goes wrong, you can always hit &lt;code&gt;ESC&lt;&#x2F;code&gt; and type &lt;code&gt;u&lt;&#x2F;code&gt; for undo.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Operations&lt;&#x2F;strong&gt;: delete, find, change, back, insert, append,…&lt;br &#x2F;&gt;
&lt;strong&gt;Objects&lt;&#x2F;strong&gt;: word, sentence, parentheses, (html) tag,… (see &lt;code&gt;:help text-objects&lt;&#x2F;code&gt;)&lt;&#x2F;p&gt;
&lt;p&gt;Inserting text is just another editing operation, which can be triggered with &lt;code&gt;i&lt;&#x2F;code&gt;.
That’s why, by default, you are in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikibooks.org&#x2F;wiki&#x2F;Learning_the_vi_Editor&#x2F;Vim&#x2F;Modes&quot;&gt;normal mode&lt;&#x2F;a&gt; — also called command mode — where all those operations work.&lt;&#x2F;p&gt;
&lt;p&gt;Once you know this, Vim makes a lot more sense, and that’s when you start to be productive.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-my-workflow-changed-over-the-years&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#how-my-workflow-changed-over-the-years&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;How My Workflow Changed Over The Years&lt;&#x2F;h2&gt;
&lt;p&gt;When I was a beginner, I was very interested in how people with more Vim experience would use the editor.
Now that I’m a long-time user, here’s my answer: there’s no secret sauce.
I certainly feel less exhausted after editing text for a day, but 90% of the commands I use fit on a post-it note.&lt;&#x2F;p&gt;
&lt;p&gt;That said, throughout the years, my Vim habits changed.&lt;br &#x2F;&gt;
I went through several phases:&lt;&#x2F;p&gt;
&lt;p&gt;Year 1: I’m happy if I can insert text and quit again.&lt;br &#x2F;&gt;
Year 2: That’s cool, let’s learn more shortcuts.&lt;br &#x2F;&gt;
Year 3-5: Let’s add &lt;em&gt;all&lt;&#x2F;em&gt; the features!!!&lt;br &#x2F;&gt;
Year 6-10: My &lt;code&gt;.vimrc&lt;&#x2F;code&gt; is five lines long.&lt;&#x2F;p&gt;
&lt;p&gt;Year three is when I started to learn the Vim ecosystem for real.
I tried all sorts of flavors like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;macvim-dev.github.io&#x2F;macvim&#x2F;&quot;&gt;MacVim&lt;&#x2F;a&gt; and distributions like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;carlhuda&#x2F;janus&quot;&gt;janus&lt;&#x2F;a&gt;.
For a while, I even maintained &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;dotVim&#x2F;blob&#x2F;master&#x2F;.vimrc&quot;&gt;my own Vim configuration
&lt;&#x2F;a&gt;, which was almost 400 lines long.&lt;&#x2F;p&gt;
&lt;p&gt;All of that certainly helped me learn what’s out there, but I’m not sure if I would recommend that to a Vim beginner.
After all, you don’t really &lt;em&gt;need&lt;&#x2F;em&gt; all of that. Start with a vanilla Vim editor which works just fine!&lt;&#x2F;p&gt;
&lt;p&gt;My current Vim setup is pretty minimalistic. I don’t use plugins anymore, mostly out of laziness and because built-in Vim commands or macros can replace them.&lt;&#x2F;p&gt;
&lt;p&gt;Here are three concrete examples of how my workflow changed over the years:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;In the beginning, I used a lot of “number powered movements”. That is, if you have a command like &lt;code&gt;b&lt;&#x2F;code&gt;, which goes back one word in the text, you can also say &lt;code&gt;5b&lt;&#x2F;code&gt; to go back five words. Nowadays I mostly use &lt;code&gt;&#x2F;&lt;&#x2F;code&gt; to move to a matching word because it’s quicker.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;I don’t use arrow keys to move around in text anymore but forced myself to use &lt;code&gt;h&lt;&#x2F;code&gt;, &lt;code&gt;j&lt;&#x2F;code&gt;, &lt;code&gt;k&lt;&#x2F;code&gt;, &lt;code&gt;l&lt;&#x2F;code&gt;. Many people say that this is faster. After trying this for a few years, I don’t think that is true (at least for me). I now just stick to it out of habit.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;On my main working machine I use Vim for quick text editing and Visual Studio Code plus the awesome &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;VSCodeVim&#x2F;Vim&quot;&gt;Vim plugin&lt;&#x2F;a&gt; for projects. This way, I get the best of both worlds.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;workflow-issues-i-still-struggle-with&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#workflow-issues-i-still-struggle-with&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Workflow Issues I Still Struggle With&lt;&#x2F;h2&gt;
&lt;p&gt;After all these years I’m still not a Vim master — far from it.
As every other Vim user will tell you, we’re all still learning.&lt;&#x2F;p&gt;
&lt;p&gt;Here are a few things I wish I could do better:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Jumping around in longer texts&lt;&#x2F;strong&gt;: I know the basics, like searching (&lt;code&gt;&#x2F;&lt;&#x2F;code&gt;), jumping to a matching bracket (&lt;code&gt;%&lt;&#x2F;code&gt;) or jumping to specific lines (for line 10, type &lt;code&gt;10G&lt;&#x2F;code&gt;), but I still could use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Symbol_(programming)&quot;&gt;symbols&lt;&#x2F;a&gt; more often for navigation.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Using visual mode for moving text around&lt;&#x2F;strong&gt;: Sometimes it can be quite complicated to type the right combination of letters to cut (delete) the text I want to move around. That’s where visual mode (&lt;code&gt;v&lt;&#x2F;code&gt;) shines. It highlights the selected text. I should use it more often.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Multiple registers for copy and paste&lt;&#x2F;strong&gt;: Right now I only use one register (like a pastebin) for copying text, but Vim supports multiple registers. That’s cool if you want to move around more than one thing at the same time. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vim.fandom.com&#x2F;wiki&#x2F;Copy%2c_cut_and_paste&quot;&gt;Let’s use more of those!&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;Tabs&lt;&#x2F;strong&gt;: I know &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;vim.fandom.com&#x2F;wiki&#x2F;Using_tab_pages&quot;&gt;how tabs work&lt;&#x2F;a&gt;, but all the typing feels clunky. That’s why I never extensively used them. Instead, I mostly use multiple terminal tabs or an IDE with Vim bindings for bigger projects.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;would-i-learn-vim-again&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#would-i-learn-vim-again&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Would I learn Vim again?&lt;&#x2F;h2&gt;
&lt;p&gt;That’s a tough question to answer.&lt;&#x2F;p&gt;
&lt;p&gt;On one side, I would say no.
There’s a steep learning curve in Vim and seeing all those modern IDEs become better at understanding the user’s intent, editing text became way easier and faster in general.&lt;&#x2F;p&gt;
&lt;p&gt;On the other side, Vim is the fastest way for me to write down my thoughts and code. As a bonus, it runs on every machine and might well be around for decades to come. In contrast, I don’t know if the IntelliJ shortcuts will be relevant in ten years (note: if you read this in the future and ask yourself “What is IntelliJ?”, the answer might be no).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;takeaways&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#takeaways&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Takeaways&lt;&#x2F;h2&gt;
&lt;p&gt;If I can give you one tip, don’t learn Vim by memorizing commands. Instead, look at your current workflow and try to make it better, then see how Vim can make that easier. It helps to look at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;yG-UaBJXZ80?t=43m12s&quot;&gt;other people using Vim to get inspired&lt;&#x2F;a&gt; (Youtube link with sound).&lt;&#x2F;p&gt;
&lt;p&gt;You will spend a lot of time writing text, so it’s well worth the time investment to learn one editor really well — especially if you are a programmer.&lt;&#x2F;p&gt;
&lt;p&gt;After ten years, Vim is somehow ingrained in my mind. I &lt;em&gt;think&lt;&#x2F;em&gt; Vim when I’m editing text. It has become yet another natural language to me. I’m looking forward to the next ten years.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Refactoring Go Code to Avoid File I&#x2F;O in Unit Tests</title>
        <published>2018-03-22T00:00:00+00:00</published>
        <updated>2021-04-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/go-io-testing/"/>
        <id>https://endler.dev/2018/go-io-testing/</id>
        
        <summary type="html">&lt;p&gt;At work today, I refactored some simple Go code to make it more testable.
The idea was to avoid file handling in unit tests without mocking or using temporary files by separating data input&#x2F;output and data manipulation.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>A Tiny `ls` Clone Written in Rust</title>
        <published>2018-03-09T00:00:00+00:00</published>
        <updated>2018-03-09T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/ls/"/>
        <id>https://endler.dev/2018/ls/</id>
        
        <content type="html" xml:base="https://endler.dev/2018/ls/">&lt;p&gt;In my series of &lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;yes&#x2F;&quot;&gt;useless Unix tools rewritten in Rust&lt;&#x2F;a&gt;, today I’m going to be covering one of my all-time favorites: &lt;code&gt;ls&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;First off, let me say that you probably don’t want to use this code as a replacement for &lt;code&gt;ls&lt;&#x2F;code&gt; on your local machine (although you could!).
As we will find out, &lt;code&gt;ls&lt;&#x2F;code&gt; is actually quite a powerful tool under the hood.
I’m not going to come up with a full rewrite, but instead only cover the very basic output that you would expect from calling &lt;code&gt;ls -l&lt;&#x2F;code&gt; on your command line.
What is this output? I’m glad you asked.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;expected-output&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#expected-output&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Expected output&lt;&#x2F;h2&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; ls -l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;drwxr-xr-x 2 mendler  staff    13468 Feb  4 11:19 Top Secret&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rwxr--r-- 1 mendler  staff  6323935 Mar  8 21:56 Never Gonna Give You Up - Rick Astley.mp3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-r--r-- 1 mendler  staff        0 Feb 18 23:55 Thoughts on Chess Boxing.doc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-rw-r--r-- 1 mendler  staff   380434 Dec 24 16:00 nobel-prize-speech.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Your output may vary, but generally, there are a couple of notable things going on. From left to right, we’ve got the following fields:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;drwx&lt;&#x2F;code&gt; things in the beginning are the &lt;em&gt;file permissions&lt;&#x2F;em&gt; (also called the file mode). If &lt;code&gt;d&lt;&#x2F;code&gt; is set, it’s a directory. &lt;code&gt;r&lt;&#x2F;code&gt; means read, &lt;code&gt;w&lt;&#x2F;code&gt; means write and &lt;code&gt;x&lt;&#x2F;code&gt; execute.
This &lt;code&gt;rwx&lt;&#x2F;code&gt; pattern gets repeated three times for the current user, the group, and other computer users respectively.&lt;&#x2F;li&gt;
&lt;li&gt;Next we got the hardlink count when referring to a file, or the number of contained directory entries when referring to a directory. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;unix.stackexchange.com&#x2F;a&#x2F;43047&quot;&gt;Reference&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;li&gt;Owner name&lt;&#x2F;li&gt;
&lt;li&gt;Group name&lt;&#x2F;li&gt;
&lt;li&gt;Number of bytes in the file&lt;&#x2F;li&gt;
&lt;li&gt;Date when the file was last modified&lt;&#x2F;li&gt;
&lt;li&gt;Finally, the path name&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For more in-depth information, I can recommend reading the manpage of &lt;code&gt;ls&lt;&#x2F;code&gt; from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;linux.die.net&#x2F;man&#x2F;1&#x2F;ls&quot;&gt;GNU coreutils&lt;&#x2F;a&gt; used in most Linux distributions and the one from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20170909164539&#x2F;https:&#x2F;&#x2F;developer.apple.com&#x2F;legacy&#x2F;library&#x2F;documentation&#x2F;Darwin&#x2F;Reference&#x2F;ManPages&#x2F;man1&#x2F;ls.1.html&quot;&gt;Darwin&lt;&#x2F;a&gt; (which powers MacOS).&lt;&#x2F;p&gt;
&lt;p&gt;Whew, that’s a lot of information for such a tiny tool.
But then again, it can’t be so hard to port that to Rust, right? Let’s get started!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-very-basic-ls-in-rust&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a-very-basic-ls-in-rust&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;A very basic &lt;code&gt;ls&lt;&#x2F;code&gt; in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;Here is the most bare-bones version of &lt;code&gt;ls&lt;&#x2F;code&gt;, which just prints all files in the current directory:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ref&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;		println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;		process&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;is_dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;read_dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;				let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;				let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; file_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;						.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;file_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;						.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;						.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;or_else&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;f&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;format!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Invalid entry: &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; f&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;				println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; file_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;	Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can copy that straight out of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fs&#x2F;fn.read_dir.html#examples&quot;&gt;documentation&lt;&#x2F;a&gt;.
When we run it, we get the expected output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; cargo run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cargo.lock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cargo.toml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It prints the files and exits. Simple enough.&lt;&#x2F;p&gt;
&lt;p&gt;We should stop for a moment and celebrate our success, knowing that we just wrote our first little Unix utility from scratch.
&lt;em&gt;Pro Tip&lt;&#x2F;em&gt;: You can install the binary with &lt;code&gt;cargo install&lt;&#x2F;code&gt; and call it like any other binary from now on.&lt;&#x2F;p&gt;
&lt;p&gt;But we have higher goals, so let’s continue.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;adding-a-parameter-to-specify-the-directory&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#adding-a-parameter-to-specify-the-directory&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Adding a parameter to specify the directory&lt;&#x2F;h2&gt;
&lt;p&gt;Usually, if we type &lt;code&gt;ls mydir&lt;&#x2F;code&gt;, we expect to get the file listing of no other directory than &lt;code&gt;mydir&lt;&#x2F;code&gt;. We should add the same functionality to our version.&lt;&#x2F;p&gt;
&lt;p&gt;To do this, we need to accept command line parameters.
One Rust crate that I love to use in this case is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TeXitoi&#x2F;structopt&quot;&gt;structopt&lt;&#x2F;a&gt;. It makes argument parsing very easy.&lt;&#x2F;p&gt;
&lt;p&gt;Add it to your &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;. (You need cargo-edit for the following command).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo add structopt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we can import it and use it in our project:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;macro_use&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; structopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; use std::...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; structopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;StructOpt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;derive&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;StructOpt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Debug&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;struct&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Opt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Output file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;structopt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;default_value &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; parse&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;from_os_str&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;	path&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; PathBuf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; opt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Opt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from_args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt;ref&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;opt&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;path&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;			println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;			process&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;	&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Same as before&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By adding the &lt;code&gt;Opt&lt;&#x2F;code&gt; struct, we can define the command line flags, input parameters, and the &lt;code&gt;help&lt;&#x2F;code&gt; output super easily.
There are tons of configuration options, so it’s worth checking out the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;TeXitoi&#x2F;structopt&quot;&gt;project homepage&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Also note, that we changed the type of the path variable from &lt;code&gt;Path&lt;&#x2F;code&gt; to &lt;code&gt;PathBuf&lt;&#x2F;code&gt;. The difference is, that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;std&#x2F;path.rs.html#1107-1109&quot;&gt;&lt;code&gt;PathBuf&lt;&#x2F;code&gt; owns the inner path string&lt;&#x2F;a&gt;, while &lt;code&gt;Path&lt;&#x2F;code&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;src&#x2F;std&#x2F;path.rs.html#1629-1631&quot;&gt;simply provides a reference to it&lt;&#x2F;a&gt;. The relationship is similar to &lt;code&gt;String&lt;&#x2F;code&gt; and &lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;reading-the-modification-time&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#reading-the-modification-time&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Reading the modification time&lt;&#x2F;h2&gt;
&lt;p&gt;Now let’s deal with the metadata.
First, we try to retrieve the modification time from the file.
A quick look at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;fs&#x2F;struct.Metadata.html&quot;&gt;the documentation&lt;&#x2F;a&gt; shows us how to do it:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;foo.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; let&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;modified&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;	println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; time&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The output might not be what you expect: we receive a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;stable&#x2F;std&#x2F;time&#x2F;struct.SystemTime.html&quot;&gt;&lt;code&gt;SystemTime&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; object, which represents the measurement of the system clock. E.g. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=96e18ed541abe896f761d601cdf50561&amp;amp;version=stable&quot;&gt;this code&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; SystemTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Prints: SystemTime { tv_sec: 1520554933, tv_nsec: 610406401 }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But the format that we would like to have is something like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Mar&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;  9&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 01&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;24&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Thankfully, there is a library called &lt;code&gt;chrono&lt;&#x2F;code&gt;, which can read this format and convert it into any human readable output we like:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; current&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Local&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;SystemTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;now&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; current&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;format&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;%_d %b %H:%M&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;this prints&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;9 Mar 01:29&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;(Yeah, I know it’s getting late.)&lt;&#x2F;p&gt;
&lt;p&gt;Armed with that knowledge, we can now read our file modification time.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo add chrono&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; chrono&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;DateTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Local&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; run&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;PathBuf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Box&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;is_dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;read_dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;dir&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;			let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;			let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; file_name&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;			let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;			let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;			let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; modified&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Local&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; DateTime&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;from&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;modified&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;			println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;				&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:&amp;gt;5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;				size&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;				modified&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;format&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;%_d %b %H:%M&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;				file_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;			)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;	Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This &lt;code&gt;{:&amp;gt;5}&lt;&#x2F;code&gt; might look weird. It’s a formatting directive provided by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fmt&#x2F;&quot;&gt;&lt;code&gt;std::fmt&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
It means “right align this field with a space padding of 5” - just like our bigger brother &lt;code&gt;ls -l&lt;&#x2F;code&gt; is doing it.&lt;&#x2F;p&gt;
&lt;p&gt;Similarly, we retrieved the size in bytes with &lt;code&gt;metadata.len()&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;unix-file-permissions-are-a-zoo&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#unix-file-permissions-are-a-zoo&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Unix file permissions are a zoo&lt;&#x2F;h2&gt;
&lt;p&gt;Reading the file permissions is a bit more tricky.
While the &lt;code&gt;rwx&lt;&#x2F;code&gt; notation is very common in Unix derivatives such as *BSD or GNU&#x2F;Linux, many other operating systems ship their own permission management.
There are even &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;File_system_permissions&quot;&gt;differences between the Unix derivatives&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Wikipedia lists a few extensions to the file permissions that you might encounter:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;+ (plus) suffix indicates an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Access_control_list&quot;&gt;access control list&lt;&#x2F;a&gt; that can control additional permissions.&lt;&#x2F;li&gt;
&lt;li&gt;. (dot) suffix indicates an &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;access.redhat.com&#x2F;documentation&#x2F;en-us&#x2F;red_hat_enterprise_linux&#x2F;6&#x2F;html&#x2F;security-enhanced_linux&#x2F;chap-security-enhanced_linux-selinux_contexts&quot;&gt;SELinux context&lt;&#x2F;a&gt; is present. Details may be listed with the command ls -Z.&lt;&#x2F;li&gt;
&lt;li&gt;@ suffix indicates &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Extended_file_attributes&quot;&gt;extended file attributes&lt;&#x2F;a&gt; are present.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;That just goes to show, that there are a lot of important details to be considered when implementing this in real life.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;implementing-very-basic-file-mode&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#implementing-very-basic-file-mode&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Implementing very basic file mode&lt;&#x2F;h2&gt;
&lt;p&gt;For now, we just stick to the basics and assume we are on a platform that supports the &lt;code&gt;rwx&lt;&#x2F;code&gt; file mode.&lt;&#x2F;p&gt;
&lt;p&gt;Behind the &lt;code&gt;r&lt;&#x2F;code&gt;, the &lt;code&gt;w&lt;&#x2F;code&gt; and the &lt;code&gt;x&lt;&#x2F;code&gt; are in reality octal numbers. That’s easier for computers to work with and many hardcore users even prefer to type the numbers over the symbols.
The ruleset behind those octals is as follows. I took that from the &lt;code&gt;chmod&lt;&#x2F;code&gt; manpage.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	Modes may be absolute or symbolic.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	An absolute mode is an octal number constructed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	from the sum of one or more of the following values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0400    Allow read by owner.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0200    Allow write by owner.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0100    For files, allow execution by owner.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0040    Allow read by group members.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0020    Allow write by group members.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0010    For files, allow execution by group members.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0004    Allow read by others.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0002    Allow write by others.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 0001    For files, allow execution by others.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For example, to set the permissions for a file so that the owner can read, write and execute it and nobody else can do anything would be 700 (400 + 200 +100).&lt;&#x2F;p&gt;
&lt;p&gt;Granted, those numbers are the same since the 70s and are not going to change soon, but it’s still a bad idea to compare our file permissions directly with the values; if not for compatibility reasons, then for readability and to avoid magic numbers in our code.&lt;&#x2F;p&gt;
&lt;p&gt;Therefore, we use the &lt;code&gt;libc&lt;&#x2F;code&gt; crate, which provides constants for those magic numbers.
As mentioned above, these file permissions are Unix specific, so we need to import a Unix-only library named &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;os&#x2F;unix&#x2F;fs&#x2F;trait.PermissionsExt.html&quot;&gt;&lt;code&gt;std::os::unix::fs::PermissionsExt;&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for that.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Examples:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; * `S_IRGRP` stands for &amp;quot;read permission for group&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; * `S_IXUSR` stands for &amp;quot;execution permission for user&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; libc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;S_IRGRP&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IROTH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IRUSR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IWGRP&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IWOTH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IWUSR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IXGRP&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IXOTH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IXUSR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;os&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;unix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;fs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;PermissionsExt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We can now get the file permissions like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; entry&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; metadata&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;permissions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;parse_permissions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; as&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;code&gt;parse_permissions()&lt;&#x2F;code&gt; is a little helper function defined as follows:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; parse_permissions&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; triplet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IRUSR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IWUSR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IXUSR&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; group&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; triplet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IRGRP&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IWGRP&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IXGRP&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;	let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; other&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; triplet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IROTH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IWOTH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; S_IXOTH&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	[&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; group&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; other&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;join&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It takes the file mode as a &lt;code&gt;u16&lt;&#x2F;code&gt; (simply because the libc constants are &lt;code&gt;u16&lt;&#x2F;code&gt;)
and calls &lt;code&gt;triplet&lt;&#x2F;code&gt; on it.
For each flag &lt;code&gt;read&lt;&#x2F;code&gt;, &lt;code&gt;write&lt;&#x2F;code&gt;, and &lt;code&gt;execute&lt;&#x2F;code&gt;, it runs a binary &lt;code&gt;&amp;amp;&lt;&#x2F;code&gt; operation on &lt;code&gt;mode&lt;&#x2F;code&gt;.
The output is matched exhaustively against all possible permission patterns.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; triplet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; read&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; write&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; execute&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u16&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	match&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; read&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; mode&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; execute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;---&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r--&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-w-&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;--x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;r-x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rw-&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;-wx&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; _&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;rwx&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	}&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;to_string&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;wrapping-up&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#wrapping-up&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Wrapping up&lt;&#x2F;h2&gt;
&lt;p&gt;The final output looks like this. Close enough.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; cargo run&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rw-r--r--     7  6 Mar 23:10 .gitignore&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rw-r--r-- 15618  8 Mar 00:41 Cargo.lock&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rw-r--r--   185  8 Mar 00:41 Cargo.toml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rwxr-xr-x   102  5 Mar 21:31 src&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rwxr-xr-x   136  6 Mar 23:07 target&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;That’s it! You can find the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;mre&#x2F;91ebb841c34df69671bd117ead621a8b&quot;&gt;final version of our toy &lt;code&gt;ls&lt;&#x2F;code&gt; on Github&lt;&#x2F;a&gt;.
We are still far away from a full-fledged &lt;code&gt;ls&lt;&#x2F;code&gt; replacement, but at least we learned a thing or two about its internals.&lt;&#x2F;p&gt;
&lt;p&gt;If you’re looking for a proper &lt;code&gt;ls&lt;&#x2F;code&gt; replacement written in Rust, go check out &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Peltoche&#x2F;lsd&quot;&gt;&lt;code&gt;lsd&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.
If, instead, you want to read another blog post from the same series, check out &lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;yes&#x2F;&quot;&gt;&lt;em&gt;A Little Story About the &lt;code&gt;yes&lt;&#x2F;code&gt; Unix Command&lt;&#x2F;em&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust in 2018</title>
        <published>2018-01-09T00:00:00+00:00</published>
        <updated>2023-01-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/rust-2018/"/>
        <id>https://endler.dev/2018/rust-2018/</id>
        
        <summary type="html">&lt;p&gt;I wrote about the &lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;future-of-rust&#x2F;&quot;&gt;future of Rust&lt;&#x2F;a&gt; before and it seems like nobody stops me from doing it again! Quite the contrary: this time the Rust core team even &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2018&#x2F;01&#x2F;03&#x2F;new-years-rust-a-call-for-community-blogposts.html&quot;&gt;asked for it&lt;&#x2F;a&gt;.
I’m a bit late to the party, but here are my 2 cents about the priorities for Rust in 2018.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Functional Programming for Mathematical Computing</title>
        <published>2018-01-02T00:00:00+00:00</published>
        <updated>2018-01-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2018/functional-mathematics/"/>
        <id>https://endler.dev/2018/functional-mathematics/</id>
        
        <content type="html" xml:base="https://endler.dev/2018/functional-mathematics/">&lt;p&gt;Programming languages help us describe general solutions for problems; the result just happens to be executable by machines. Every programming language comes with a different set of strengths and weaknesses, one reason being that its syntax and semantics heavily influence the range of problems which can easily be tackled with it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;tl;dr:&lt;&#x2F;strong&gt; &lt;em&gt;I think that functional programming is better suited for mathematical computations than the more common imperative approach.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;using-built-in-abstractions-for-mathematics&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#using-built-in-abstractions-for-mathematics&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Using built-in abstractions for Mathematics&lt;&#x2F;h2&gt;
&lt;p&gt;The ideas behind a language (the underlying programming paradigms) are distinctive for the community that builds around it. The developers create a unique ecosystem of ready-to-use libraries and frameworks around the language core. As a consequence, some languages are stronger in areas such as business applications (one could think of Cobol), others work great for systems programming (like C or Rust).&lt;&#x2F;p&gt;
&lt;p&gt;When it comes to solving mathematical and numerical problems with computers, Fortran might come to mind. Although Fortran is a general-purpose language, it is mostly known for scientific computing. Of course, the language was created with that purpose in mind – hence the name, &lt;em&gt;Formula Translation&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;One reason for its popularity in this area is that it offers some built-in domain-specific keywords to express mathematical concepts, while keeping an eye on performance. For instance, it has a dedicated datatype for complex numbers – &lt;code&gt;COMPLEX&lt;&#x2F;code&gt; – and a keyword named &lt;code&gt;DIMENSION&lt;&#x2F;code&gt; which is quite similar to the mathematical term and can be used to create arrays and vectors.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;imperative-vs-functional-style&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#imperative-vs-functional-style&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Imperative vs functional style&lt;&#x2F;h2&gt;
&lt;p&gt;Built-in keywords can help expand the expressiveness of a language into a specific problem space, but this approach is severly limited. It’s not feasible to extend the language core &lt;em&gt;ad infinitum&lt;&#x2F;em&gt;; it would just be harder to maintain and take longer to learn. Therefore, most languages provide other ways of abstraction – like &lt;em&gt;functions&lt;&#x2F;em&gt;, &lt;em&gt;subroutines&lt;&#x2F;em&gt;, &lt;em&gt;classes&lt;&#x2F;em&gt; and &lt;em&gt;objects&lt;&#x2F;em&gt; – to split a routine into smaller, more manageable parts. These mechanisms might help to control the complexity of a program, but especially when dealing with mathematical problems, one has to be careful not to obfuscate the solution with boilerplate code.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;specimen-i-factorial&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#specimen-i-factorial&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Specimen I - Factorial&lt;&#x2F;h3&gt;
&lt;p&gt;As an example, the stated problem might be to translate the following formula, which calculates the factorial of a positive number n, into program code:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2018&#x2F;functional-mathematics&#x2F;.&#x2F;example_faculty.svg&quot; alt=&quot;The mathematical definition of a faculty: n! = 1 * 2 * 3 … * n&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;An implementation of the above formula using imperative style Java might look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-primitive z-storage z-type z-primitive z-java&quot;&gt; long&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fact&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;final&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-primitive z-storage z-type z-primitive z-java&quot;&gt; int&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;        &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Negative numbers not allowed&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-primitive z-storage z-type z-primitive z-java&quot;&gt;    long&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; prod&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-primitive z-storage z-type z-primitive z-java&quot;&gt;int&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span&gt; i &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;lt;=&lt;&#x2F;span&gt;&lt;span&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ++&lt;&#x2F;span&gt;&lt;span&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        prod &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*=&lt;&#x2F;span&gt;&lt;span&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span&gt; prod&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is quite a long solution for such a short problem definition.
(Note that writing a version with an explicit loop from 1 to n was on purpose; a recursive function would be shorter, but uses a concept which was not introduced by the mathematical formula.)&lt;&#x2F;p&gt;
&lt;p&gt;Also, the program contains many language-specific keywords, such as &lt;code&gt;public&lt;&#x2F;code&gt;, &lt;code&gt;static&lt;&#x2F;code&gt;, and &lt;code&gt;System.err.println()&lt;&#x2F;code&gt;. On top of that, the programmer must explicitly provide all data types for the variables in use – a tiresome obligation.&lt;&#x2F;p&gt;
&lt;p&gt;All of this obfuscates the mathematical definition.&lt;&#x2F;p&gt;
&lt;p&gt;Compare this with the following version written in a functional language, like Haskell.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;fact n &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; product &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is an almost direct translation from the problem definition into code. It needs no explicit types, no temporary variables and no access modifiers (such as public).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;specimen-ii-dot-product&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#specimen-ii-dot-product&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Specimen II - Dot product&lt;&#x2F;h3&gt;
&lt;p&gt;One could argue that the above Haskell program owes its brevity to the fact, that the language provides just the right abstractions (namely the &lt;code&gt;product&lt;&#x2F;code&gt; keyword and the &lt;code&gt;[1..n]&lt;&#x2F;code&gt; range syntax) for that specific task.
Therfore let’s examine a simple function which is neither available in Haskell nor in Java: The dot product of two vectors. The mathematical definition is as follows:&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2018&#x2F;functional-mathematics&#x2F;.&#x2F;example_vector_dot.svg&quot; alt=&quot;The mathematical definition of a vector dot product: a·b= aibi =a1b1+a2b2+···+anbn =abT&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For vectors with three dimensions, it can be written as&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2018&#x2F;functional-mathematics&#x2F;.&#x2F;example_vector_3d.svg&quot; alt=&quot;Vector dot product for three dimentsions: a·b = a1 * b1 + a2 * b2 + a3* b3&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;First, a Haskell implementation:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;type&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-haskell z-storage z-type&quot;&gt; Scalar&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;data&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-haskell z-storage z-type&quot;&gt; Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; deriving&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-haskell z-storage z-type&quot;&gt;Show&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;dot&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-haskell z-storage z-type&quot;&gt;Num&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-haskell z-storage z-type&quot;&gt; Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-haskell z-storage z-type&quot;&gt; Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-haskell z-storage z-type&quot;&gt; Scalar&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;Vector&lt;&#x2F;span&gt;&lt;span&gt; a1 a2 a3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-keyword z-operator&quot;&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;dot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-keyword z-operator&quot;&gt;`&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;Vector&lt;&#x2F;span&gt;&lt;span&gt; b1 b2 b3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; a1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;b1 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; a2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;b2 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span&gt; a3&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;b3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note, that the mathematical types can be defined in one line each. Further note, that we define the dot function in infix notation, that is, we place the first argument of dot in front of the function name and the second argument behind it. This way, the code looks more like its mathematical equivalent.
An example call of the above function would be&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;haskell&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ’&lt;&#x2F;span&gt;&lt;span&gt;dot&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;’&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;which is short, precise and readable.&lt;&#x2F;p&gt;
&lt;p&gt;Now, a similar implementation in Java.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-generic z-java&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; extends&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-generic z-java&quot;&gt; Number&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;    private&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt; T&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language z-this z-variable z-language&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language z-this z-variable z-language&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-language z-this z-variable z-language&quot;&gt;        this&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;z&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-primitive z-storage z-type z-primitive z-java&quot;&gt; double&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; dot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt;Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;        return&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;doubleValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;doubleValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;doubleValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;doubleValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; +&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;doubleValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; v&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;z&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;doubleValue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-primitive z-storage z-type z-primitive z-java&quot;&gt; void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type z-object z-array z-java&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span&gt; args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type z-java&quot;&gt;        Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type z-generic z-java&quot;&gt;Integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type z-java&quot;&gt; Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type z-generic z-java&quot;&gt;Integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type z-java&quot;&gt;        Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type z-generic z-java&quot;&gt;Integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; b&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; new&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type z-java&quot;&gt; Vector&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type z-generic z-java&quot;&gt;Integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        System&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;println&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;dot&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For a proper textual representation of Vectors, the toString() Method would also need to be overwritten. In Haskell, one can simply derive from the &lt;code&gt;Show&lt;&#x2F;code&gt; typeclass as shown in the code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;creating-new-abstractions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#creating-new-abstractions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Creating new abstractions&lt;&#x2F;h2&gt;
&lt;p&gt;If functions and types are not sufficient to write straightforward programs, Haskell also offers simple constructs to create new operators and keywords which extend the language core itself. This makes domain-specific-languages feasible and enables the developer to work more directly on the actual problem instead of working around peculiarities of the programming language itself (such as memory management or array iteration). Haskell embraces this concept; Java has no such functionality.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#conclusion&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;I’m not trying to bash Java or worship Haskell here. Both languages have their place.
I merely picked Java, because lots of programmers can read it.&lt;&#x2F;p&gt;
&lt;p&gt;The comparison is more between a functional and an imperative approach for numerical and symbolical programming; and for that, I prefer a functional approach every day. It removes clutter and yields elegant solutions. It provides convenient methods to work on a high level of abstraction and speak in mathematical terms and still, these strengths are disregarded by many programmers.&lt;&#x2F;p&gt;
&lt;p&gt;Abraham H. Maslow’s observation in his 1966 book &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.goodreads.com&#x2F;book&#x2F;show&#x2F;1510050.The_Psychology_of_Science&quot;&gt;The Psychology of Science&lt;&#x2F;a&gt; seems fitting:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;“I suppose it is tempting, if the only tool you have is a hammer, to treat everything as if it were a nail.”&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Rust for Rubyists</title>
        <published>2017-12-17T00:00:00+00:00</published>
        <updated>2023-01-02T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/rust-for-rubyists/"/>
        <id>https://endler.dev/2017/rust-for-rubyists/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/rust-for-rubyists/">&lt;p&gt;Recently I came across a delightful article on idiomatic Ruby.
I’m not a good Ruby developer by any means, but I realized, that a lot of the patterns are also quite common in Rust.
What follows is a side-by-side comparison of idiomatic code in both languages.&lt;&#x2F;p&gt;
&lt;p&gt;The Ruby code samples are from the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;medium.com&#x2F;the-renaissance-developer&#x2F;idiomatic-ruby-1b5fa1445098&quot;&gt;original article&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;map-and-higher-order-functions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#map-and-higher-order-functions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Map and Higher-Order Functions&lt;&#x2F;h2&gt;
&lt;p&gt;The first example is a pretty basic iteration over elements of a container using &lt;code&gt;map&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;user_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; users&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; user&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;map&lt;&#x2F;code&gt; concept is also pretty standard in Rust.
Compared to Ruby, we need to be a little more explicit here:
If &lt;code&gt;users&lt;&#x2F;code&gt; is a vector of &lt;code&gt;User&lt;&#x2F;code&gt; objects, we first need to create an iterator from it:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=5a61b7b44ff01fabbc07dba9409d9b97&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; user_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; users&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;You might say that’s quite verbose, but this additional abstraction allows us to express an important concept:
will the iterator take ownership of the vector, or will it not?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;With &lt;code&gt;iter()&lt;&#x2F;code&gt;, you get a “read-only view” into the vector. After the iteration, it will be unchanged.&lt;&#x2F;li&gt;
&lt;li&gt;With &lt;code&gt;into_iter()&lt;&#x2F;code&gt;, you take ownership over the vector. After the iteration, the vector will be gone.
In Rust terminology, it will have &lt;em&gt;moved&lt;&#x2F;em&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Read some more about the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hermanradtke.com&#x2F;2015&#x2F;06&#x2F;22&#x2F;effectively-using-iterators-in-rust.html&quot;&gt;difference between &lt;code&gt;iter()&lt;&#x2F;code&gt; and &lt;code&gt;into_iter()&lt;&#x2F;code&gt; here&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The above Ruby code can be simplified like this:&lt;&#x2F;p&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;user_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; users&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-language&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In Ruby, higher-order functions (like &lt;code&gt;map&lt;&#x2F;code&gt;) take &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.appsignal.com&#x2F;2018&#x2F;09&#x2F;04&#x2F;ruby-magic-closures-in-ruby-blocks-procs-and-lambdas.html&quot;&gt;blocks or procs&lt;&#x2F;a&gt; as an argument and the language provides a convenient shortcut for method invocation — &lt;code&gt;&amp;amp;:id&lt;&#x2F;code&gt; is the same as &lt;code&gt;{|o| o.id()}&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Something similar could be done in Rust:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=131027a481d4691821315ad308d26dc9&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; id&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;u&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; u&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; user_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; users&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;This is probably not the most idiomatic way to do it, though. What you will see more often is the use of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;first-edition&#x2F;ufcs.html&quot;&gt;Universal Function Call Syntax&lt;&#x2F;a&gt; in this case:&lt;sup&gt;&lt;a href=&quot;#fn1&quot; id=&quot;ref1&quot;&gt;1&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=51069ee76e5d534621ccd6633474b630&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; user_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; users&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;In Rust, higher-order functions take &lt;strong&gt;functions&lt;&#x2F;strong&gt; as an argument. Therefore &lt;code&gt;users.iter().map(Users::id)&lt;&#x2F;code&gt; is more or less equivalent to &lt;code&gt;users.iter().map(|u| u.id())&lt;&#x2F;code&gt;.&lt;sup&gt;&lt;a href=&quot;#fn2&quot; id=&quot;ref2&quot;&gt;2&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Also, &lt;code&gt;map()&lt;&#x2F;code&gt; in Rust returns another iterator and not a collection.
If you want a collection, you would have to run &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#examples-23&quot;&gt;&lt;code&gt;collect()&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; on that, as we’ll see later.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;iteration-with-each&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#iteration-with-each&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Iteration with Each&lt;&#x2F;h2&gt;
&lt;p&gt;Speaking of iteration, one pattern that I see a lot in Ruby code is this:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;mre&#x2F;f6552360a4c08f2c064da7f00d434d5c&quot;&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Ruby&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Rust&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Python&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Cobol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;each&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; do&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;|&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;  puts&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section z-embedded&quot;&gt;#{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-meta z-embedded&quot;&gt;lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Since &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.rust-lang.org&#x2F;2017&#x2F;10&#x2F;12&#x2F;Rust-1.21.html&quot;&gt;Rust 1.21&lt;&#x2F;a&gt;, this is now also possible:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=549d38bc43549fd5444c731d2bc3a47b&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Ruby&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Rust&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Python&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Cobol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;for_each&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Although, more commonly one would write that as a normal for-loop in Rust:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=a7691b56b1dfd1fb19aa00a91b39589d&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Ruby&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Rust&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Python&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Cobol&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; lang&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;h2 id=&quot;select-and-filter&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#select-and-filter&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Select and filter&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s say you want to extract only even numbers from a collection in Ruby.&lt;&#x2F;p&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;even_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;element&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; element &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; element&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;even?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; [ni, 2, nil, 4, nil]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;even_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; even_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;compact&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; [2, 4]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In this example, before calling &lt;code&gt;compact&lt;&#x2F;code&gt;, our &lt;code&gt;even_numbers&lt;&#x2F;code&gt; array had &lt;code&gt;nil&lt;&#x2F;code&gt; entries.
Well, in Rust there is no concept of &lt;code&gt;nil&lt;&#x2F;code&gt; or &lt;code&gt;Null&lt;&#x2F;code&gt;. You don’t need a &lt;code&gt;compact&lt;&#x2F;code&gt;.
Also, &lt;code&gt;map&lt;&#x2F;code&gt; doesn’t take predicates. You would use &lt;code&gt;filter&lt;&#x2F;code&gt; for that:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=494d6e3ff016c21931e3495b10c8f6ee&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; even_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;element&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; element&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;or, to make a vector out of the result&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=45c6dbd2d35316c73165c5571d66df9d&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Result: [2, 4]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; even_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;element&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; element&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Some hints:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I’m using the type hint &lt;code&gt;Vec&amp;lt;i64&amp;gt;&lt;&#x2F;code&gt; here because, without it, Rust does not know what collection I want to build when calling &lt;code&gt;collect&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;vec!&lt;&#x2F;code&gt; is a macro for creating a vector.&lt;&#x2F;li&gt;
&lt;li&gt;Instead of &lt;code&gt;iter&lt;&#x2F;code&gt;, I use &lt;code&gt;into_iter&lt;&#x2F;code&gt;. This way, I take ownership of the elements in the vector. With &lt;code&gt;iter()&lt;&#x2F;code&gt; I would get a &lt;code&gt;Vec&amp;lt;&amp;amp;i64&amp;gt;&lt;&#x2F;code&gt; instead.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In Rust, there is no &lt;code&gt;even&lt;&#x2F;code&gt; method on numbers, but that doesn’t keep us from defining one!&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=c289c2a1cf8bd870cbd5cc2cd60ea791&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; even&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; even_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;even&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;In a real-world scenario, you would probably use a third-party package (crate) like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-num&#x2F;num&quot;&gt;&lt;code&gt;num&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; for numerical mathematics:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=e4bbbf60b7b1cbbedfb363672731bf53&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; num&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; num&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Integer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; even_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;i64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;is_even&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;In general, it’s quite common to use crates in Rust for functionality that is not in the standard lib.
Part of the reason why this is so well accepted is that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;cargo&quot;&gt;cargo&lt;&#x2F;a&gt; is such a rad package manager.
(Maybe because it was built by no other than &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;yehudakatz.com&#x2F;about&#x2F;&quot;&gt;Yehuda Katz&lt;&#x2F;a&gt; of Ruby fame. 😉)&lt;&#x2F;p&gt;
&lt;p&gt;As mentioned before, Rust does not have &lt;code&gt;nil&lt;&#x2F;code&gt;. However, there is still the concept of operations that can fail.
The canonical type to express that is called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;result&#x2F;&quot;&gt;&lt;code&gt;Result&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Let’s say you want to convert a vector of strings to integers.&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=1365d177503ee2d32c4aa594263ee4d4&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; maybe_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nah&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nope&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; maybe_numbers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;That looks nice, but maybe the output is a little unexpected. &lt;code&gt;numbers&lt;&#x2F;code&gt; will also contain the parsing errors:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=1365d177503ee2d32c4aa594263ee4d4&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;ParseIntError&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kind&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; InvalidDigit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Err&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;ParseIntError&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; kind&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; InvalidDigit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Sometimes you’re just interested in the successful operations.
An easy way to filter out the errors is to use &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.filter_map&quot;&gt;&lt;code&gt;filter_map&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=afdc823ec2e165ac0a03948fb323d305&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; maybe_numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; vec!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nah&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;nope&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; numbers&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; maybe_numbers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter_map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;parse&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;I changed two things here:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Instead of &lt;code&gt;map&lt;&#x2F;code&gt;, I’m now using &lt;code&gt;filter_map&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;code&gt;parse&lt;&#x2F;code&gt; returns a &lt;code&gt;Result&lt;&#x2F;code&gt;, but &lt;code&gt;filter_map&lt;&#x2F;code&gt; expects an &lt;code&gt;Option&lt;&#x2F;code&gt;. We can convert a &lt;code&gt;Result&lt;&#x2F;code&gt; into an &lt;code&gt;Option&lt;&#x2F;code&gt; by calling &lt;code&gt;ok()&lt;&#x2F;code&gt; on it&lt;sup&gt;&lt;a href=&quot;#fn3&quot; id=&quot;ref3&quot;&gt;3&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The return value contains all successfully converted strings:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=afdc823ec2e165ac0a03948fb323d305&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;The &lt;code&gt;filter_map&lt;&#x2F;code&gt; is similar to the &lt;code&gt;select&lt;&#x2F;code&gt; method in Ruby:&lt;&#x2F;p&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt;select&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;element&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;|&lt;&#x2F;span&gt;&lt;span&gt; element&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;even?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;random-numbers&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#random-numbers&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Random numbers&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s how to get a random number from an array in Ruby:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=a66785b44094bacb78fa8dd822bfeab5&amp;version=stable&quot;&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;sample&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;That’s quite nice and idiomatic!
Compare that to Rust:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=bed7fca31737bcbf4b9aed427cc22713&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rng&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thread_rng&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;rng&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;choose&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;For the code to work, you need the &lt;code&gt;rand&lt;&#x2F;code&gt; crate. Click on the snippet for a running example.&lt;&#x2F;p&gt;
&lt;p&gt;There are some differences to Ruby. Namely, we need to be more explicit about what random number generator
we want &lt;em&gt;exactly&lt;&#x2F;em&gt;. We decide for a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.rs&#x2F;rand&#x2F;latest&#x2F;rand&#x2F;fn.thread_rng.html&quot;&gt;lazily-initialized thread-local random number generator, seeded by the system&lt;&#x2F;a&gt;.
In this case, I’m using a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;slice&#x2F;&quot;&gt;slice&lt;&#x2F;a&gt; instead of a vector. The main difference is that the slice has a fixed size while the vector does not.&lt;&#x2F;p&gt;
&lt;p&gt;Within the standard library, Rust doesn’t have a &lt;code&gt;sample&lt;&#x2F;code&gt; or &lt;code&gt;choose&lt;&#x2F;code&gt; method on the slice itself.
That’s a design decision: the core of the language is kept small to allow evolving the language in the future.&lt;&#x2F;p&gt;
&lt;p&gt;This doesn’t mean that you cannot have a nicer implementation today.
For instance, you could define a &lt;code&gt;Choose&lt;&#x2F;code&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;second-edition&#x2F;ch10-00-generics.html&quot;&gt;trait&lt;&#x2F;a&gt; and implement it for &lt;code&gt;[T]&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=a66785b44094bacb78fa8dd822bfeab5&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; rand&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; rand&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span&gt;thread_rng&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Rng&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;trait&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Choose&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; choose&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;impl&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Choose&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;    fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; choose&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Option&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;T&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;        let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; rng&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; thread_rng&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        rng&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;choose&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;This boilerplate could be put into a crate to make it reusable for others.
With that, we arrive at a solution that rivals Ruby’s elegance.&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=a66785b44094bacb78fa8dd822bfeab5&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 16&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 32&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;choose&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;h2 id=&quot;implicit-returns-and-expressions&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#implicit-returns-and-expressions&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Implicit returns and expressions&lt;&#x2F;h2&gt;
&lt;p&gt;Ruby methods automatically return the result of the last statement.&lt;&#x2F;p&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get_user_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;users&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  users&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-language&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Same for Rust. Note the missing semicolon.&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=c7130debb2f712269380bd04819069ff&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; get_user_ids&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;users&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;User&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    users&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; user&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;id&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;But in Rust, this is just the beginning, because &lt;em&gt;everything&lt;&#x2F;em&gt; is an expression.
The following block splits a string into characters, removes the &lt;code&gt;h&lt;&#x2F;code&gt;, and returns the result as a &lt;code&gt;HashSet&lt;&#x2F;code&gt;.
This &lt;code&gt;HashSet&lt;&#x2F;code&gt; will be assigned to &lt;code&gt;x&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=9ad54a58d3e5f1c06e795b5f7dca451e&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; HashSet&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;_&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Get unique chars of a word {&amp;#39;h&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;l&amp;#39;, &amp;#39;o&amp;#39;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; unique&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;hello&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;chars&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;    &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; filter out the &amp;#39;h&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    unique&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;h&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Same works for conditions:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=cec96176079e8812ff62ad84a432ac9d&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;absolutely!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; else&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;no seriously&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Since a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;1.2.0&#x2F;book&#x2F;match.html&quot;&gt;&lt;code&gt;match&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; statement is also an expression, you can assign the result to a variable, too!&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=a6b32fae6257787432cf607f5772693e&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;enum&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Meter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Yard&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Angstroem&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Lightyear&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; length_in_meters&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Meter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Yard&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;91&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Angstroem&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0000000001&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;    Unit&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Lightyear&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-numeric&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;461&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;e&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;+&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;15&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;h2 id=&quot;multiple-assignments&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#multiple-assignments&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Multiple Assignments&lt;&#x2F;h2&gt;
&lt;p&gt;In Ruby you can assign multiple values to variables in one step:&lt;&#x2F;p&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;def&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; two&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; three &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span&gt; values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In Rust, you can only decompose tuples into tuples, but not a vector into a tuple for example.
So this will work:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=11b02c318ec35456b8247c3161cb341b&amp;version=nightly&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; two&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; three&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;But this won’t:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=11b02c318ec35456b8247c3161cb341b&amp;version=nightly&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; two&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; three&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;    ^^^^^^^^^^^^^^^^^ expected array of 3 elements, found tuple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Neither will this:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=11b02c318ec35456b8247c3161cb341b&amp;version=nightly&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; two&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; three&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;iter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;collect&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; a collection of type `(_, _, _)` cannot be built from an iterator over elements of type `&amp;amp;{integer}`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;But with nightly Rust, you can now do this:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=11b02c318ec35456b8247c3161cb341b&amp;version=nightly&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;one&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; two&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; three&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 3&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;On the other hand, there’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;second-edition&#x2F;ch18-03-pattern-syntax.html&quot;&gt;a lot more you can do with destructuring&lt;&#x2F;a&gt; apart from multiple assignments. You can write beautiful, ergonomic code using pattern syntax.&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=969612861bc6028e3b98345e21a4289e&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; x&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;    4&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 5&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; y&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;yes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;no&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;To quote &lt;em&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;book&#x2F;second-edition&#x2F;ch18-03-pattern-syntax.html&quot;&gt;The Book&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;This prints &lt;code&gt;no&lt;&#x2F;code&gt; since the if condition applies to the whole pattern &lt;code&gt;4 | 5 | 6&lt;&#x2F;code&gt;, not only to the last value 6.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;h2 id=&quot;string-interpolation&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#string-interpolation&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;String interpolation&lt;&#x2F;h2&gt;
&lt;p&gt;Ruby has &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;ruby-doc.org&#x2F;docs&#x2F;ruby-doc-bundle&#x2F;ProgrammingRuby&#x2F;book&#x2F;ref_m_kernel.html#Kernel.sprintf&quot;&gt;extensive string interpolation support&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;div class=&quot;ruby lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;programming_language&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Ruby&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section z-embedded&quot;&gt;#{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string z-meta z-embedded&quot;&gt;programming_language&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-punctuation z-section z-embedded&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is a beautiful programming language&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This can be translated like so:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=6920e723137e44c4befe3398721fafa1&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; programming_language&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Rust&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;format!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is also a beautiful programming language&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; programming_language&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Named arguments are also possible, albeit much less common:&lt;&#x2F;p&gt;
&lt;a class=&quot;example&quot; href=&quot;https:&#x2F;&#x2F;play.rust-lang.org&#x2F;?gist=6920e723137e44c4befe3398721fafa1&amp;version=stable&quot;&gt;
&lt;div class=&quot;rust lang-icon&quot;&gt;&lt;&#x2F;div&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;language&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; is also a beautiful programming language&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; language&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Rust&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;a&gt;
&lt;p&gt;Rust’s &lt;code&gt;println!()&lt;&#x2F;code&gt; syntax is even more extensive than Ruby’s. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;fmt&#x2F;&quot;&gt;Check the docs&lt;&#x2F;a&gt; if you’re curious about what else you can do.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;that-s-it&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#that-s-it&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;That’s it!&lt;&#x2F;h2&gt;
&lt;p&gt;Ruby comes with syntactic sugar for many common usage patterns, which allows for very elegant code.
Low-level programming and raw performance are no primary goals of the language.&lt;&#x2F;p&gt;
&lt;p&gt;If you do need that, Rust might be a good fit, because it provides fine-grained hardware control with comparable ergonomics.
If in doubt, Rust favors explicitness, though; it eschews magic.&lt;&#x2F;p&gt;
&lt;p&gt;Did I whet your appetite for idiomatic Rust? Have a look at &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;idiomatic-rust&quot;&gt;this Github project&lt;&#x2F;a&gt;. I’d be thankful for contributions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;footnotes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#footnotes&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Footnotes&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;sup id=&quot;fn1&quot;&gt;1. Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;Argorak&quot;&gt;Florian Gilcher&lt;&#x2F;a&gt; for the hint.&lt;a href=&quot;#ref1&quot; title=&quot;Jump back to footnote 1 in the text.&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;br &#x2F;&gt;
&lt;sup id=&quot;fn2&quot;&gt;2. Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;user&#x2F;masklinn&quot;&gt;masklin&lt;&#x2F;a&gt; for pointing out multiple inaccuracies.&lt;a href=&quot;#ref2&quot; title=&quot;Jump back to footnote 2 in the text.&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;br &#x2F;&gt;
&lt;sup id=&quot;fn3&quot;&gt;3. In the first version, I sait that &lt;code&gt;ok()&lt;&#x2F;code&gt; would convert a &lt;code&gt;Result&lt;&#x2F;code&gt; into a &lt;code&gt;boolean&lt;&#x2F;code&gt;, which was wrong. Thanks to &lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=16003080&quot;&gt;isaacg&lt;&#x2F;a&gt; for the correction.&lt;a href=&quot;#ref3&quot; title=&quot;Jump back to footnote 3 in the text.&quot;&gt;↩&lt;&#x2F;a&gt;&lt;&#x2F;sup&gt;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Making Myself Obsolete</title>
        <published>2017-12-10T00:00:00+00:00</published>
        <updated>2025-10-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/obsolete/"/>
        <id>https://endler.dev/2017/obsolete/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/obsolete/">&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;obsolete&amp;#x2F;dinosaur.svg&quot; 
        
            alt=&quot;The Stegosaurus had better days 150 million years ago.&quot;
        

        

        
        
        
            width=&quot;1187&quot;
        
        
            height=&quot;531&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            The Stegosaurus had better days 150 million years ago.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: Paleontologists once thought it had a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Stegosaurus#.22Second_brain.22&quot;&gt;brain in its butt&lt;&#x2F;a&gt;.
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In December 2015 I was looking for static analysis tools to integrate into &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tech.trivago.com&#x2F;&quot;&gt;trivago&lt;&#x2F;a&gt;’s CI process.
The idea was to detect typical programming mistakes automatically.
That’s quite a common thing, and there are lots of helpful tools out there which fit the bill.&lt;&#x2F;p&gt;
&lt;p&gt;So I looked for a list of tools…&lt;&#x2F;p&gt;
&lt;p&gt;To my surprise, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_tools_for_static_code_analysis&quot;&gt;the only list I found was on Wikipedia&lt;&#x2F;a&gt; — and it was outdated.
There was no such project on Github, where most modern static analysis tools were hosted.&lt;&#x2F;p&gt;
&lt;p&gt;Without overthinking it, I opened up my editor and wrote down a few tools I found through my initial research. After that, I pushed the list to Github.&lt;&#x2F;p&gt;
&lt;p&gt;I called the project &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;analysis-tools-dev&#x2F;static-analysis&quot;&gt;Awesome Static Analysis&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Fast forward two years and the list has grown quite a bit.
So far, it has 75 contributors, 277 forks, and received over 2,000 stars.
(Thanks for all the support!)
(Update May 2018: 91 contributors, 363 forks, over 3,000 stars.)
(Update October 2025: 316 contributors, 1,400 forks, over 14,000 stars.)&lt;&#x2F;p&gt;
&lt;p&gt;Around 1000 unique visitors find the list every week. Not much by any means, but I feel obliged to keep it up-to-date
because it has become an essential source of information for many people.&lt;&#x2F;p&gt;
&lt;p&gt;It now lists around 300 tools for static analysis. Everything from Ada to TypeScript is on there.
What I find particularly motivating is, that now the authors themselves create pull requests to add their tools!&lt;&#x2F;p&gt;
&lt;p&gt;There was one problem though: The list of pull requests got longer and longer, as I was busy doing other things.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;obsolete&amp;#x2F;pull_requests.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;obsolete&amp;#x2F;pull_requests.jpg&quot; 
        
            alt=&quot;The list of Github Pull requests for awesome-static-analysis&quot;
        

        

        
        
        
            width=&quot;650&quot;
        
        
            height=&quot;528&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            The list of Github Pull requests for awesome-static-analysis
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;h2 id=&quot;adding-contributors&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#adding-contributors&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Adding contributors&lt;&#x2F;h2&gt;
&lt;p&gt;I always try to make team members out of regular contributors. My friend and colleague &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;andygrunwald&quot;&gt;Andy Grunwald&lt;&#x2F;a&gt; as well as &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;impredicative&quot;&gt;Ouroboros Chrysopoeia&lt;&#x2F;a&gt; are both valuable collaborators. They help me weed out new PRs whenever they find the time.&lt;&#x2F;p&gt;
&lt;p&gt;But let’s face it: checking the pull requests is a dull, manual task.
What needs to be checked for each new tool can be summarized like this:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Formatting rules are satisfied&lt;&#x2F;li&gt;
&lt;li&gt;Project URL is reachable&lt;&#x2F;li&gt;
&lt;li&gt;License annotation is correct&lt;&#x2F;li&gt;
&lt;li&gt;Tools of each section are alphabetically ordered&lt;&#x2F;li&gt;
&lt;li&gt;Description is not too long&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I guess it’s obvious what we should do with that checklist: automate it!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-linter-for-linting-linters&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a-linter-for-linting-linters&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;A linter for linting linters&lt;&#x2F;h2&gt;
&lt;p&gt;So why not write an analysis tool, which checks our list of analysis tools!
What sounds pretty meta, is actually pretty straightforward.&lt;&#x2F;p&gt;
&lt;p&gt;With every pull request, we trigger our bot, which checks the above rules and responds with a result.&lt;&#x2F;p&gt;
&lt;p&gt;The first step was to read the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.github.com&#x2F;v3&#x2F;guides&#x2F;building-a-ci-server&#x2F;&quot;&gt;Github documentation about building a CI server&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Just for fun, I wanted to create the bot in &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;Rust&lt;&#x2F;a&gt;.
The two most popular Github clients for Rust were github-rs (now deprecated) and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;softprops&#x2F;hubcaps&quot;&gt;hubcaps&lt;&#x2F;a&gt;.
Both looked pretty neat, but then I found &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;softprops&#x2F;afterparty&quot;&gt;afterparty&lt;&#x2F;a&gt;, a “Github webhook server”.&lt;&#x2F;p&gt;
&lt;p&gt;The example looked fabulous:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;#&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;macro_use&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; log&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; env_logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; afterparty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;extern&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; crate&lt;&#x2F;span&gt;&lt;span&gt; hyper&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; afterparty&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Delivery&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Hub&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; hyper&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Server&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;    env_logger&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;init&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; addr&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;0.0.0.0:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 4567&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; hub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Hub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    hub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;pull_request&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;delivery&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Delivery&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;        match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; delivery&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;payload &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;            Event&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;PullRequest&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ref&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; ref&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; sender&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;                &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; TODO: My code here!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;                println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;sender &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; action &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; sender&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;login&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; action&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; srvc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Server&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;http&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;addr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                   .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                   .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;handle&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;hub&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;listening on &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; addr&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    srvc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This allowed me to focus on the actual analysis code,
which makes for a pretty boring read. It mechanically checks for the things mentioned above and could be written in any language.
If you want to have a look (or even contribute!), &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;awesome-static-analysis-ci&quot;&gt;check out the repo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;talking-to-github&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#talking-to-github&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Talking to Github&lt;&#x2F;h2&gt;
&lt;p&gt;After the analysis code was done, I had a bot, running locally, waiting for incoming pull requests.&lt;&#x2F;p&gt;
&lt;p&gt;But how could I talk to Github?&lt;br &#x2F;&gt;
I found out, that I should use the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.github.com&#x2F;v3&#x2F;repos&#x2F;statuses&#x2F;&quot;&gt;Status API&lt;&#x2F;a&gt;
and send a &lt;code&gt;POST&lt;&#x2F;code&gt; request to &lt;code&gt;&#x2F;repos&#x2F;mre&#x2F;awesome-static-analysis&#x2F;statuses&#x2F;:sha&lt;&#x2F;code&gt;&lt;br &#x2F;&gt;
(&lt;code&gt;:sha&lt;&#x2F;code&gt; is the commit ID that points to the &lt;code&gt;HEAD&lt;&#x2F;code&gt; of the pull request):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;state&amp;quot;: &amp;quot;success&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;quot;description&amp;quot;: &amp;quot;The build succeeded!&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I could have used one of the existing Rust Github clients, but I decided to write a simple function to update the pull request status code.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; set_status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;status&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; desc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; repo&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; sha&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;str&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Result&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;reqwest&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Response&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; token&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;var&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;GITHUB_TOKEN&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; reqwest&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Client&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; HashMap&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;state&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; status&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    params&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;insert&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;description&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; desc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Sending status: &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;:#?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; params&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; status_url&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; format!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;api.github.com&#x2F;repos&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&#x2F;statuses&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; repo&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; sha&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Status url: &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; status_url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;    Ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;client&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;request&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;            reqwest&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Method&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Post&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;            &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;format!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;                &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;?access_token=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                status_url&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                token&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            )&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        )&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;json&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;params&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;        .&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;send&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can see that I pass in a Github token from the environment and then I send the &lt;code&gt;JSON&lt;&#x2F;code&gt; payload as a post request using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;seanmonstar&#x2F;reqwest&quot;&gt;reqwest&lt;&#x2F;a&gt; library.&lt;&#x2F;p&gt;
&lt;p&gt;That turned out to become a problem in the end: while afterparty was using version 0.9 of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;hyperium&#x2F;hyper&quot;&gt;hyper&lt;&#x2F;a&gt;, reqwest was using 0.11. Unfortunately, these two versions depend on a different build of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crates.io&#x2F;crates&#x2F;openssl-sys&quot;&gt;openssl-sys&lt;&#x2F;a&gt; bindings. That’s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;cargo&#x2F;issues&#x2F;886&quot;&gt;well-known problem&lt;&#x2F;a&gt; and the only way to fix it, is to resolve the conflict.&lt;&#x2F;p&gt;
&lt;p&gt;I was stuck for a while, but then I saw, that there was an open pull request to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;softprops&#x2F;afterparty&#x2F;pull&#x2F;26&quot;&gt;upgrade afterparty to hyper 0.10&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So inside my &lt;code&gt;Cargo.toml&lt;&#x2F;code&gt;, I locked the version of afterparty to the version of the pull request:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;dependencies&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;afterparty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; git&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;https:&#x2F;&#x2F;github.com&#x2F;ms705&#x2F;afterparty&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This fixed the build, and I could finally move on.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deployment&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#deployment&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Deployment&lt;&#x2F;h2&gt;
&lt;p&gt;I needed a place to host the bot.&lt;&#x2F;p&gt;
&lt;p&gt;Preferably for free, as it was a non-profit Open Source project.
Also, the provider would have to run binaries.&lt;&#x2F;p&gt;
&lt;p&gt;For quite some time, I was following a product named &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zeit.co&#x2F;&quot;&gt;zeit&lt;&#x2F;a&gt;.
It runs any Docker container using an intuitive command line interface called &lt;code&gt;now&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I fell in love the first time I saw their demo on the site, so I wanted to give it a try.&lt;&#x2F;p&gt;
&lt;p&gt;So I added a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;docs.docker.com&#x2F;engine&#x2F;userguide&#x2F;eng-image&#x2F;multistage-build&#x2F;&quot;&gt;multi-stage Dockerfile&lt;&#x2F;a&gt; to my project:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;docker&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; rust &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; builder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; . &#x2F;usr&#x2F;src&#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;WORKDIR&lt;&#x2F;span&gt;&lt;span&gt; &#x2F;usr&#x2F;src&#x2F;app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; cargo build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; debian:stretch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;RUN&lt;&#x2F;span&gt;&lt;span&gt; apt update \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;amp;&amp;amp; apt install -y libssl1.1 ca-certificates \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;amp;&amp;amp; apt clean -y \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;amp;&amp;amp; apt autoclean -y \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;amp;&amp;amp; apt autoremove -y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;COPY&lt;&#x2F;span&gt;&lt;span&gt; --from=builder target&#x2F;release&#x2F;check .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;EXPOSE&lt;&#x2F;span&gt;&lt;span&gt; 4567&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;ENTRYPOINT&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;.&#x2F;check&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-other z-special-method z-dockerfile z-keyword&quot;&gt;CMD&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;--help&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The first part would build a static binary, the second part would run it at container startup.
Well, that didn’t work, because &lt;code&gt;zeit&lt;&#x2F;code&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;zeit&#x2F;now&#x2F;issues&#x2F;962&quot;&gt;does not support multi-stage builds yet&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The workaround was to split up the Dockerfile into two and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;awesome-static-analysis-ci&#x2F;blob&#x2F;master&#x2F;Makefile&quot;&gt;connect them both with a Makefile&lt;&#x2F;a&gt;. Makefiles are pretty powerful, &lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;makefiles&#x2F;&quot;&gt;you know&lt;&#x2F;a&gt;?&lt;&#x2F;p&gt;
&lt;p&gt;With that, I had all the parts for deployment together.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Build Rust binary for Linux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;docker run --rm -v $(CURDIR):&#x2F;usr&#x2F;src&#x2F;ci -w &#x2F;usr&#x2F;src&#x2F;ci rust cargo build --release&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Deploy Docker images built from the local Dockerfile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;now deploy --force --public -e GITHUB_TOKEN=${GITHUB_TOKEN}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Set domain name of new build to `check.now.sh`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# (The deployment URL was copied to the clipboard and is retrieved with pbpaste on macOS)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;now alias `pbpaste` check.now.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here’s the output of the deploy using &lt;code&gt;now&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Deploying ~&#x2F;Code&#x2F;private&#x2F;awesome-static-analysis-ci&#x2F;deploy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Ready! https:&#x2F;&#x2F;deploy-sjbiykfvtx.now.sh (copied to clipboard) [2s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Initializing…&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Initializing…&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Building&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; ▲ docker build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Sending build context to Docker daemon 2.048 kBkB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Step 1 : FROM mre0&#x2F;ci:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; latest: Pulling from mre0&#x2F;ci&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Digest: sha256:5ad07c12184755b84ca1b587e91b97c30f7d547e76628645a2c23dc1d9d3fd4b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Status: Downloaded newer image for mre0&#x2F;ci:latest&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt;  ---&amp;gt; 8ee1b20de28b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Successfully built 8ee1b20de28b&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; ▲ Storing image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; ▲ Deploying image&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; ▲ Container started&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; listening on 0.0.0.0:4567&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;gt; Deployment complete!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The last step was to add &lt;code&gt;check.now.sh&lt;&#x2F;code&gt; as a webhook inside the awesome-static-analysis &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developer.github.com&#x2F;webhooks&#x2F;creating&#x2F;&quot;&gt;project settings&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, whenever a new pull request is coming in, you see that little bot getting active!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;2017&#x2F;obsolete&#x2F;pull_request_success.jpg&quot; alt=&quot;A successful pull request, which was checked by the bot&quot; &#x2F;&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;outcome-and-future-plans&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#outcome-and-future-plans&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Outcome and future plans&lt;&#x2F;h2&gt;
&lt;p&gt;I am very pleased with my choice of tools: afterparty saved me from a lot of manual work, while zeit made deployment really easy.&lt;br &#x2F;&gt;
It feels like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;lambda&#x2F;features&#x2F;&quot;&gt;Amazon Lambda&lt;&#x2F;a&gt; on steroids.&lt;&#x2F;p&gt;
&lt;p&gt;If you look at the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;awesome-static-analysis-ci&#x2F;blob&#x2F;master&#x2F;src&#x2F;main.rs&quot;&gt;code&lt;&#x2F;a&gt; and the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;awesome-static-analysis-ci&#x2F;commits&#x2F;master&quot;&gt;commits&lt;&#x2F;a&gt; for my bot, you can see all my little missteps, until I got everything just right. Turns out, parsing human-readable text is tedious.&lt;br &#x2F;&gt;
Therefore I was thinking about turning the list of analysis tools into a structured format like &lt;code&gt;YAML&lt;&#x2F;code&gt;. This would greatly simplify the parsing and have the added benefit of having a machine-readable list of tools that can be used for other projects.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;update-may-2018&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#update-may-2018&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Update May 2018&lt;&#x2F;h2&gt;
&lt;p&gt;While attending the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.wearedevelopers.com&#x2F;&quot;&gt;WeAreDevelopers conference in Vienna&lt;&#x2F;a&gt; (can recommend that), I moved the CI pipeline from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;zeit.co&#x2F;&quot;&gt;zeit.co&lt;&#x2F;a&gt; to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;travis-ci.org&#x2F;&quot;&gt;Travis CI&lt;&#x2F;a&gt;.
The reason was, that I wanted the linting code next to the project, which greatly simplified things.
First and foremost I don’t need the web request handling code anymore, because travis takes care of that.
If you like, you can compare the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;awesome-static-analysis-ci&#x2F;blob&#x2F;master&#x2F;src&#x2F;main.rs&quot;&gt;old&lt;&#x2F;a&gt; and the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;analysis-tools-dev&#x2F;static-analysis&#x2F;blob&#x2F;d03bd8a602b231205915a4403e2b6dc4159962f8&#x2F;ci&#x2F;src&#x2F;lib.rs&quot;&gt;new&lt;&#x2F;a&gt; version.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;update-october-2025&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#update-october-2025&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Update October 2025&lt;&#x2F;h2&gt;
&lt;p&gt;Most everything about that project has changed since then.
I now use Github Actions to run the CI checks, and the &lt;code&gt;README.md&lt;&#x2F;code&gt; is completely auto-generated from the YAML files for each tool.
We support specia metadata fields like a list of additional resources (tutorials, videos, etc) or the list of paid plans a tool offers.
We have a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;analysis-tools.dev&#x2F;&quot;&gt;fancy website&lt;&#x2F;a&gt; now, where we list all 700+ tools and allow people to vote.
The website is built with Next.js and uses Algolia for search.
We also have a bunch of sponsors now, who help us pay for hosting and other expenses.
It’s crazy to see how projects grow if you give them some love and your time!
I hope this serves as an inspiration for you to start your own open source project!
It’s not that hard, and incredibly rewarding.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Modern Day Annoyances - Digital Clocks</title>
        <published>2017-11-07T00:00:00+00:00</published>
        <updated>2017-11-07T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/digitial-clocks/"/>
        <id>https://endler.dev/2017/digitial-clocks/</id>
        
        <summary type="html">&lt;p&gt;This morning I woke up to the beeping noise of our oven’s alarm clock.
The reason was that I tried to correct the oven’s local time the day before — and I pushed the wrong buttons.
As a result I didn’t set the correct time, instead, I set a cooking timer… and that’s what woke me up today.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Learn Some Rust During Hacktoberfest</title>
        <published>2017-10-15T00:00:00+00:00</published>
        <updated>2017-10-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/hacktoberfest/"/>
        <id>https://endler.dev/2017/hacktoberfest/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/hacktoberfest/">&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;hacktoberfest&amp;#x2F;hacktoberfest.svg&quot; 
        
            alt=&quot;Dirndl, Lederhose, Brezn, Beer, Rust&quot;
        

        

        
        
        
            width=&quot;330&quot;
        
        
            height=&quot;90&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            Dirndl, Lederhose, Brezn, Beer, Rust
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freepik.com&#x2F;free-vector&#x2F;food-items-oktoberfest-festival_911290.htm&quot;&gt;Designed by Freepik&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;October is the perfect time to contribute to Open Source — at least according to Github and DigitalOcean.
Because that’s when they organize Hacktoberfest, a global event where you &lt;strong&gt;get a free shirt and lots of street cred&lt;&#x2F;strong&gt; for creating pull requests. Read the official announcement &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;hacktoberfest.digitalocean.com&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Some people think they cannot contribute anything of value. Either because they lack the programming skills or because they don’t know where to start.&lt;&#x2F;p&gt;
&lt;p&gt;This guide is trying to change that!&lt;&#x2F;p&gt;
&lt;p&gt;Let me show you, how &lt;em&gt;everybody&lt;&#x2F;em&gt; can contribute code to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&#x2F;&quot;&gt;Rust&lt;&#x2F;a&gt;, a safe systems programming language.
I was inspired to write this by a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;llogiq&#x2F;status&#x2F;915288482314178560&quot;&gt;tweet from llogiq&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;1-find-a-great-rust-project-to-work-on&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#1-find-a-great-rust-project-to-work-on&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;1. Find a great Rust project to work on&lt;&#x2F;h2&gt;
&lt;p&gt;We all want our work to be appreciated.&lt;br &#x2F;&gt;
Therefore I suggest to start contributing to medium-sized projects, because they gained some momentum but are still driven by a small number of maintainers, so help is always welcome. By contrast, tiny projects are mostly useful to the original author only, while large projects can be intimidating at first and have stricter guidelines.&lt;&#x2F;p&gt;
&lt;p&gt;For now, let’s look at repositories with 5-100 stars, which were updated within this year.
Github supports &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;help.github.com&#x2F;articles&#x2F;understanding-the-search-syntax&quot;&gt;advanced search options based on Lucene syntax&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;language:Rust stars:5..100 pushed:&amp;gt;2017-01-01&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;search?q=language%3ARust+stars%3A5..100+pushed%3A%3E2017-01-01&quot;&gt;Here&lt;&#x2F;a&gt;’s a list of projects, which match this filter.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;2-install-the-rust-toolchain&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#2-install-the-rust-toolchain&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;2. Install the Rust toolchain&lt;&#x2F;h2&gt;
&lt;p&gt;To start contributing, we need a working Rust compiler and the cargo package manager.
Fortunately, the installation should be straightforward.
I recommend &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rustup.rs&#x2F;&quot;&gt;rustup&lt;&#x2F;a&gt; for that.&lt;&#x2F;p&gt;
&lt;p&gt;Run the following command in your terminal, then follow the onscreen instructions.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;curl https:&#x2F;&#x2F;sh.rustup.rs -sSf | sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you’re unsure, just accept the defaults.
After the installation is done, we also need to get the nightly version of the compiler for later.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rustup install nightly&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Questions so far? Find more detailed installation instructions &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;asquera.de&#x2F;blog&#x2F;2017-03-03&#x2F;setting-up-a-rust-devenv&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;3-fork-the-project-and-clone-it-to-your-computer&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#3-fork-the-project-and-clone-it-to-your-computer&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;3. Fork the project and clone it to your computer&lt;&#x2F;h2&gt;
&lt;p&gt;First, click on the little &lt;em&gt;fork&lt;&#x2F;em&gt; button on the top right of the Github project page. Then clone your fork to your computer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git clone git@github.com:yourusername&#x2F;project.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For more detailed instructions, go &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;guides.github.com&#x2F;activities&#x2F;forking&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;4-does-it-build&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#4-does-it-build&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;4. Does it build?&lt;&#x2F;h2&gt;
&lt;p&gt;Before we start modifying the codebase, we should make sure that it is in a workable state.
The following commands should work right away from inside the project folder.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo build&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo test&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If not, you might want to consult the &lt;code&gt;README&lt;&#x2F;code&gt; for further instructions. (But feel free to choose another project.)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;5-the-magic-sauce&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#5-the-magic-sauce&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;5. The magic sauce&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s the trick: we use a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Lint_(software)&quot;&gt;linter&lt;&#x2F;a&gt; called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rust-lang&#x2F;rust-clippy&quot;&gt;clippy&lt;&#x2F;a&gt; to show us improvement areas in any Rust codebase.&lt;&#x2F;p&gt;
&lt;p&gt;To get clippy, install it like so:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo +nightly install clippy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Afterwards, run it from the project root as often as you like.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rustup run nightly cargo clippy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This should give you actionable information on how to improve the codebase.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s some sample output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;warning&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; useless&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; use&lt;&#x2F;span&gt;&lt;span&gt; of `format&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;!&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;   -&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;mach&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span&gt;header&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;420&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt;49&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;420 &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;             let&lt;&#x2F;span&gt;&lt;span&gt; error &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;Error&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Malformed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;format&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;bytes size is smaller than an &lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Mach&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&lt;&#x2F;span&gt;&lt;span&gt;o header&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                                                 ^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; note&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span&gt;warn&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;useless_format&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; on&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; by&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; help&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; further&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; information&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; visit&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; https&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;rust-lang-nursery.github.io&#x2F;rust-clippy&#x2F;v0.0.165&#x2F;index.html#useless_format&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;warning&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; this&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; expression&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; borrows&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; a&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; reference&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; that&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; is&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; immediately&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; dereferenced&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; by&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; the&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; compiler&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;   -&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;-&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;mach&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;header&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rs&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;423&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;36&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;423&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; |&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;             let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; magic&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; mach&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;peek&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;                                    ^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;^&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; help&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; change&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; this&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; to&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; `&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;bytes&lt;&#x2F;span&gt;&lt;span&gt;`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; help&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; further&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; information&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; visit&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; https&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt;rust-lang-nursery.github.io&#x2F;rust-clippy&#x2F;v0.0.165&#x2F;index.html#needless_borrow&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Just try some of the suggestions and see if the project still compiles and the tests still pass.
Check out the links to the documentation in the help section to learn more.
Start small to make your changes easier to review.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;6-creating-a-pull-request&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#6-creating-a-pull-request&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;6. Creating a Pull Request&lt;&#x2F;h2&gt;
&lt;p&gt;If you’re happy with your changes, now is the time to publish them!
It’s best to create a new branch for your changes and then push it to your fork.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git checkout -b codestyle&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git commit -am &amp;quot;Minor codestyle fixes&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;git push --set-upstream origin codestyle&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Afterwards, go to the homepage of your fork on Github.
There should be a button titled &lt;em&gt;Compare &amp;amp; pull request&lt;&#x2F;em&gt;.
Please add a meaningful description and then submit the pull request.&lt;&#x2F;p&gt;
&lt;p&gt;Congratulations! You’ve contributed to the Rust ecosystem. Thank you! 🎉&lt;&#x2F;p&gt;
&lt;h2 id=&quot;trophy-case&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#trophy-case&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Trophy case&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;m4b&#x2F;goblin&#x2F;pull&#x2F;55&quot;&gt;m4b&#x2F;goblin&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gimli-rs&#x2F;cpp_demangle&#x2F;pull&#x2F;100&quot;&gt;fitzgen&#x2F;cpp_demangle&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;fdehau&#x2F;tui-rs&#x2F;pull&#x2F;19&quot;&gt;fdehau&#x2F;tui-rs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;christophertrml&#x2F;rs-natural&#x2F;pull&#x2F;15&quot;&gt;christophertrml&#x2F;rs-natural&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;bonus&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#bonus&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Bonus!&lt;&#x2F;h2&gt;
&lt;p&gt;If all of the manual fixing and checking sounds too dull, you can automate step number 5 using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;killercup&#x2F;rustfix&quot;&gt;&lt;code&gt;rustfix&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; by Pascal Hertleif (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;killercup&#x2F;&quot;&gt;@killercup&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rustfix --yolo &amp;amp;&amp;amp; cargo check&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</content>
        
    </entry>
    <entry xml:lang="en">
        <title>A Little Story About the `yes` Unix Command</title>
        <published>2017-10-10T00:00:00+00:00</published>
        <updated>2021-04-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/yes/"/>
        <id>https://endler.dev/2017/yes/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/yes/">&lt;p&gt;What’s the simplest Unix command you know?&lt;br &#x2F;&gt;
There’s &lt;code&gt;echo&lt;&#x2F;code&gt;, which prints a string to stdout and &lt;code&gt;true&lt;&#x2F;code&gt;, which always terminates with an exit code of 0.&lt;&#x2F;p&gt;
&lt;p&gt;Among the series of simple Unix commands, there’s also &lt;code&gt;yes&lt;&#x2F;code&gt;.
If you execute it without arguments, you get an infinite stream of y’s, separated by a newline:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;y&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;(...you get the idea)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;What seems to be pointless in the beginning turns out to be pretty helpful :&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;yes | sh boring_installation.sh&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Ever installed a program, which required you to type “y” and hit enter to keep going?
&lt;code&gt;yes&lt;&#x2F;code&gt; to the rescue! It will carefully fulfill its duty, so you can keep watching &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=yhBExhldRXQ&quot;&gt;Pootie Tang&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;writing-yes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#writing-yes&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Writing yes&lt;&#x2F;h2&gt;
&lt;p&gt;Here’s a basic version in… uhm… BASIC.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;10 PRINT &amp;quot;y&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;20 GOTO 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here’s the same thing in Python:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;while&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; True&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;    print&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Simple, eh? Not so quick!&lt;br &#x2F;&gt;
Turns out, that program is quite slow.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;python yes.py | pv -r &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[4.17MiB&#x2F;s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Compare that with the built-in version on my Mac:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;yes | pv -r &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[34.2MiB&#x2F;s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So I tried to write a quicker version in Rust. Here’s my first attempt:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; expletive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;nth&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    println!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; expletive&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Some explanations:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The string we want to print in a loop is the first command line parameter and is named &lt;em&gt;expletive&lt;&#x2F;em&gt;. I learned this word from the &lt;code&gt;yes&lt;&#x2F;code&gt; manpage.&lt;&#x2F;li&gt;
&lt;li&gt;I use &lt;code&gt;unwrap_or&lt;&#x2F;code&gt; to get the &lt;em&gt;expletive&lt;&#x2F;em&gt; from the parameters. In case the parameter is not set, we use “y” as a default.&lt;&#x2F;li&gt;
&lt;li&gt;The default parameter gets converted from a string slice (&lt;code&gt;&amp;amp;str&lt;&#x2F;code&gt;) into an &lt;em&gt;owned&lt;&#x2F;em&gt; string on the heap (&lt;code&gt;String&lt;&#x2F;code&gt;) using &lt;code&gt;into()&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Let’s test it.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cargo run --release | pv -r &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;   Compiling yes v0.1.0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Finished release [optimized] target(s) in 1.0 secs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;     Running `target&#x2F;release&#x2F;yes`&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[2.35MiB&#x2F;s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Whoops, that doesn’t look any better. It’s even slower than the Python version!
That caught my attention, so I looked around for the source code of a C implementation.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dspinellis&#x2F;unix-history-repo&#x2F;blob&#x2F;4c37048d6dd7b8f65481c8c86ef8cede2e782bb3&#x2F;usr&#x2F;src&#x2F;cmd&#x2F;yes.c&quot;&gt;very first version of the program&lt;&#x2F;a&gt;, released with Version 7 Unix and famously authored by Ken Thompson on &lt;nobr&gt;Jan 10, 1979&lt;&#x2F;nobr&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;argc&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; argv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-built-in z-primitive z-storage z-type&quot;&gt;char&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;*&lt;&#x2F;span&gt;&lt;span&gt;argv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  for&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;    printf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-other z-placeholder&quot;&gt;%s&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; argc&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;?&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; argv&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;No magic here.&lt;&#x2F;p&gt;
&lt;p&gt;Compare that to the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coreutils&#x2F;coreutils&#x2F;blame&#x2F;master&#x2F;src&#x2F;yes.c&quot;&gt;128-line-version from the GNU coreutils, which is mirrored on Github&lt;&#x2F;a&gt;. After 25 years, &lt;em&gt;it is still under active development!&lt;&#x2F;em&gt;
The last code change happened around a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;coreutils&#x2F;coreutils&#x2F;commit&#x2F;4cdb1703aff044de44d27e0558714542197f6dad&quot;&gt;year ago&lt;&#x2F;a&gt;.
That’s quite fast:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# brew install coreutils&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;gyes | pv -r &amp;gt; &#x2F;dev&#x2F;null&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[854MiB&#x2F;s]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The important part is at the end:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;c&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; Repeatedly output the buffer until there is a write error; then fail.  &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;while&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;full_write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt;STDOUT_FILENO&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; buf&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; bufused&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span&gt; bufused&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  continue&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Aha! So they simply use a buffer to make write operations faster.
The buffer size is defined by a constant named &lt;code&gt;BUFSIZ&lt;&#x2F;code&gt;, which gets chosen on each system so as to make I&#x2F;O efficient (see &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;libc&#x2F;manual&#x2F;html_node&#x2F;Controlling-Buffering.html&quot;&gt;here&lt;&#x2F;a&gt;).
On my system, that was defined as 1024 bytes. I actually had better performance with 8192 bytes.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve extended my Rust program:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; BufWriter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; BUFSIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 8192&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; expletive&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;nth&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap_or&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; writer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; BufWriter&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;with_capacity&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt;BUFSIZE&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    loop&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;        writeln!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;writer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; expletive&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;unwrap&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The important part is, that the buffer size is a multiple of four, to ensure &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;381368&#x2F;270334&quot;&gt;memory alignment&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Running that gave me 51.3MiB&#x2F;s.
Faster than the version, which comes with my system, but still way slower than the results from &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;unix&#x2F;comments&#x2F;6gxduc&#x2F;how_is_gnu_yes_so_fast&#x2F;&quot;&gt;this Reddit post&lt;&#x2F;a&gt; that I found, where the author talks about 10.2GiB&#x2F;s.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;update&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#update&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Update&lt;&#x2F;h2&gt;
&lt;p&gt;Once again, the Rust community did not disappoint.&lt;br &#x2F;&gt;
As soon as this post &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;75fll1&#x2F;a_little_story_about_the_yes_unix_command&#x2F;&quot;&gt;hit the Rust subreddit&lt;&#x2F;a&gt;, user &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;user&#x2F;nwydo&quot;&gt;nwydo&lt;&#x2F;a&gt; pointed out a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust&#x2F;comments&#x2F;4wde08&#x2F;optimising_yes_any_further_ideas&#x2F;&quot;&gt;previous discussion&lt;&#x2F;a&gt; on the same topic.
Here’s their optimized code, that breaks the 3GB&#x2F;s mark on my machine:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-language&quot;&gt;self&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span&gt;process&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;borrow&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;Cow&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;ffi&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;OsString&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt; const&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; BUFFER_CAPACITY&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; usize&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 64&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1024&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; to_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;os_str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; OsString&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt; Vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;  use&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; std&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;os&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;unix&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;ffi&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type z-rust z-entity z-name z-type&quot;&gt;OsStringExt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  os_str&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;into_vec&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fill_up_buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;a&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; output&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; buffer_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;  buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;buffer_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;clone_from_slice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;output&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  while&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; buffer_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;len&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;    let&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;left&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; right&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;split_at_mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;buffer_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    right&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;buffer_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;clone_from_slice&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;left&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    buffer_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; *=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;  &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;buffer_size&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;output&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt; io&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; locked&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; stdout&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;lock&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; [&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;0&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric z-entity z-name z-type&quot;&gt;u8&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant&quot;&gt; BUFFER_CAPACITY&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-type&quot;&gt;  let&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; filled&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; fill_up_buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; buffer&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; output&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;  while&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; locked&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;write_all&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;filled&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;is_ok&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;  write&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;&amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;env&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;args_os&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;nth&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;to_bytes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;map_or&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;    Cow&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Borrowed&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;      &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;y&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    )&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;    |&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;mut&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; arg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;      arg&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;push&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;b&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;\&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-character z-escape&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;      Cow&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;Owned&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;arg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  )&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-namespace&quot;&gt;  process&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;::&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;exit&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now that’s a whole different ballgame!&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;We prepare a filled string buffer, which will be reused for each loop.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;io&#x2F;struct.Stdout.html#method.lock&quot;&gt;Stdout is protected by a lock&lt;&#x2F;a&gt;. So, instead of constantly acquiring and releasing it, we keep it all the time.&lt;&#x2F;li&gt;
&lt;li&gt;We use a the platform-native &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;ffi&#x2F;struct.OsString.html&quot;&gt;&lt;code&gt;std::ffi::OsString&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;borrow&#x2F;enum.Cow.html&quot;&gt;&lt;code&gt;std::borrow::Cow&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to avoid unnecessary allocations.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The only thing that I could contribute was &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;cgati&#x2F;yes&#x2F;pull&#x2F;3&#x2F;files&quot;&gt;removing an unnecessary &lt;code&gt;mut&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. 😅&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lessons-learned&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#lessons-learned&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Lessons learned&lt;&#x2F;h2&gt;
&lt;p&gt;The trivial program &lt;code&gt;yes&lt;&#x2F;code&gt; turns out not to be so trivial after all.
It uses output buffering and memory alignment to improve performance.
Re-implementing Unix tools is fun and makes me appreciate the nifty tricks,
which make our computers fast.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Lightning Fast Image Previews with Pure CSS and LQIP</title>
        <published>2017-09-18T00:00:00+00:00</published>
        <updated>2017-09-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/image-previews/"/>
        <id>https://endler.dev/2017/image-previews/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/image-previews/">&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;image-previews&amp;#x2F;factory.svg&quot; 
        
            alt=&quot;Adapted from &amp;lt;a href=&amp;#x27;https:&amp;#x2F;&amp;#x2F;www.freepik.com&amp;#x2F;free-vector&amp;#x2F;industrial-machine-vector_753558.htm&amp;#x27;&amp;gt;Freepik&amp;lt;&amp;#x2F;a&amp;gt; &quot;
        

        

        
        
        
            width=&quot;800&quot;
        
        
            height=&quot;500&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: Adapted from &lt;a href=&#x27;https:&#x2F;&#x2F;www.freepik.com&#x2F;free-vector&#x2F;industrial-machine-vector_753558.htm&#x27;&gt;Freepik&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;My website is reasonably fast.&lt;&#x2F;p&gt;
&lt;p&gt;I hope that every page load feels snappy, no matter your device or location.
That should not come as a surprise. After all, I’m just using plain HTML and CSS.
JavaScript is avoided whenever possible.&lt;&#x2F;p&gt;
&lt;p&gt;There was one thing left, which really annoyed me: layout reflow after images got loaded.&lt;&#x2F;p&gt;
&lt;p&gt;The problem is, that the image dimensions are not known when the text is ready to be displayed.
As a result, the text will be pushed down on the screen as soon as an image is loaded above.&lt;&#x2F;p&gt;
&lt;p&gt;Also, while an image is loading, there is no preview, just blank space.
Here’s what that looks like on a slower connection:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;image-previews&amp;#x2F;fout.png&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;image-previews&amp;#x2F;fout.png&quot; 
        
            alt=&quot;Illustration of a flash of unstyled content&quot;
        

        

        
        
        
            width=&quot;543&quot;
        
        
            height=&quot;220&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Illustration of a flash of unstyled content
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;I could fix that, by hardcoding the image width and height, but that would be tedious and error-prone.
And there would be no preview.
So I was wondering, what others were doing. 🤔&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tiny-image-thumbnails&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#tiny-image-thumbnails&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Tiny image thumbnails&lt;&#x2F;h2&gt;
&lt;p&gt;I vaguely remembered, that &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;code.fb.com&#x2F;uncategorized&#x2F;the-technology-behind-preview-photos&#x2F;&quot;&gt;Facebook uses tiny preview thumbnails in their mobile app&lt;&#x2F;a&gt;.
They extract the quantization table from the JPEG header to render the preview. This information
is stored on the client, so it doesn’t need to be downloaded every time.
Unfortunately, this approach requires full control over the image encoder.
It works for apps, but hardly for websites.&lt;&#x2F;p&gt;
&lt;p&gt;The search continued.&lt;&#x2F;p&gt;
&lt;p&gt;Until my colleague &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;tobias.is&#x2F;&quot;&gt;Tobias Baldauf&lt;&#x2F;a&gt; introduced me to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.guypo.com&#x2F;introducing-lqip-low-quality-image-placeholders&quot;&gt;LQIP (Low-Quality Image Placeholders)&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the idea:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Load the page including inlined, low-quality image thumbnails.&lt;&#x2F;li&gt;
&lt;li&gt;Once the page is fully loaded (e.g. when the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.w3schools.com&#x2F;jsref&#x2F;event_onload.asp&quot;&gt;&lt;code&gt;onload&lt;&#x2F;code&gt; event&lt;&#x2F;a&gt; is fired), lazy load full quality images.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Unfortunately, this technique requires JavaScript.
Nevertheless, I liked the idea, so I started experimenting with different image sizes and formats. My goal was to create the smallest thumbnails using any standard image format.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;benchmark&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#benchmark&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Benchmark&lt;&#x2F;h2&gt;
&lt;p&gt;Here are 15 pixel wide thumbnails encoded in different file formats:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;image-previews&amp;#x2F;thumbnails.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;image-previews&amp;#x2F;thumbnails.jpg&quot; 
        
            alt=&quot;Comparison of different image formats when creating thumbnails&quot;
        

        

        
        
        
            width=&quot;600&quot;
        
        
            height=&quot;604&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Comparison of different image formats when creating thumbnails
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;I used different tools to create the thumbnails.
For JPEG and PNG encoding, I used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;shakiba&#x2F;svgexport&quot;&gt;svgexport&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;svgexport&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; img.svg&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; img.png&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;svg{background:white;}&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 15:&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; 1%&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For webp, I used &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;developers.google.com&#x2F;speed&#x2F;webp&#x2F;docs&#x2F;cwebp&quot;&gt;cwebp&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;cwebp&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; img.png&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;o&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; img.webp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The gif was converted using an online tool and optimized using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;kohler&#x2F;gifsicle&quot;&gt;gifsicle&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;gifsicle&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-option&quot;&gt;O3&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; img.gif&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt; img_mini.gif&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;comparison&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#comparison&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Comparison&lt;&#x2F;h2&gt;
&lt;p&gt;WebP is the smallest, but it’s &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;caniuse.com&#x2F;?search=webp&quot;&gt;not supported by all browsers&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
Gif was second, but when resizing the image and applying the blur filter, I was not happy with the result.&lt;br &#x2F;&gt;
In the end, I settled for PNG, which provided an excellent tradeoff between size and quality.
I optimized the images even further using &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;shssoichiro&#x2F;oxipng&quot;&gt;oxipng&lt;&#x2F;a&gt;, which supports zopfli compression.
With that, I end up with thumbnails of around 300-400 bytes in size.&lt;&#x2F;p&gt;
&lt;p&gt;I integrated the thumbnail creation process into my build toolchain for the blog.
The actual code to create the images is rather boring.
If you &lt;em&gt;really&lt;&#x2F;em&gt; want to have a look, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mre&#x2F;lqip&#x2F;&quot;&gt;it’s on Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;avoiding-javascript&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#avoiding-javascript&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Avoiding JavaScript&lt;&#x2F;h2&gt;
&lt;p&gt;Here is the skeleton HTML for the image previews:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;html&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;figure&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;loader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;object&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; data&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;image.svg&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; type&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;image&#x2F;svg+xml&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;object&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;img&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;frozen&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-other z-attribute-name z-html z-entity z-other z-attribute-name&quot;&gt; src&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;data:image&#x2F;png;base64,...&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;div&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-begin z-html z-punctuation z-definition z-tag&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag&quot;&gt;figure&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-tag z-end z-html z-punctuation z-definition z-tag&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The trick is to wrap both the full-size image and the preview image into a &lt;code&gt;loader&lt;&#x2F;code&gt; div,
which gets a &lt;code&gt;width: auto&lt;&#x2F;code&gt; CSS attribute:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css z-entity z-other z-attribute-name z-class z-css&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name z-class z-css&quot;&gt;loader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  position&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; relative&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  overflow&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; hidden&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  width&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; auto&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I wrap the SVG into an &lt;code&gt;object&lt;&#x2F;code&gt; tag instead of using an &lt;code&gt;img&lt;&#x2F;code&gt; element.
This has the benefit, that I can show a placeholder in case the SVG can’t be loaded.
I position the &lt;code&gt;object&lt;&#x2F;code&gt; at the top left of the &lt;code&gt;loader&lt;&#x2F;code&gt; div.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css z-entity z-other z-attribute-name z-class z-css&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name z-class z-css&quot;&gt;loader&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-entity z-name z-tag z-css&quot;&gt; object&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  position&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; absolute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css z-entity z-other z-attribute-name z-class z-css&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name z-class z-css&quot;&gt;loader&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-entity z-name z-tag z-css&quot;&gt; img&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css z-entity z-other z-attribute-name z-class z-css&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name z-class z-css&quot;&gt;loader&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-tag z-entity z-name z-tag z-css&quot;&gt; object&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; block&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  top&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  left&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  width&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here’s the placeholder &lt;em&gt;hack&lt;&#x2F;em&gt; including some references:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;29111371&#x2F;270334 &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;&#x2F;*&lt;&#x2F;span&gt;&lt;span class=&quot;z-comment&quot;&gt; https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;32928240&#x2F;270334 &lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-definition z-comment z-comment&quot;&gt;*&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-tag z-entity z-name z-tag z-css&quot;&gt;object&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  position&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; relative&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  float&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; left&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; block&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;  &amp;amp;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value&quot;&gt;:after {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-meta z-property-value&quot;&gt;    position: &lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt;absolute&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    top&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    left&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    display&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; block&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    width&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    height&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1000&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    content&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    background&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-constant z-other z-color z-rgb-value&quot;&gt; #&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-constant z-other z-color z-rgb-value&quot;&gt;efefef&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The last part is the handling of the thumbnails.
Like most other sites, I decided to apply a blur filter.
In a way, it looks like the image is &lt;em&gt;frozen&lt;&#x2F;em&gt;, so that’s what I called the CSS selector.
I also applied a scaling transformation to achieve sharp borders.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-entity z-css z-entity z-other z-attribute-name z-class z-css&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-entity z-other z-attribute-name z-class z-css&quot;&gt;frozen&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-vendored z-property-name&quot;&gt;  -webkit-filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; blur&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-vendored z-property-name&quot;&gt;  -moz-filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; blur&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-vendored z-property-name&quot;&gt;  -o-filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; blur&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-vendored z-property-name&quot;&gt;  -ms-filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; blur&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  filter&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; blur&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;8&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;px&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  transform&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; scale&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1.04&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  animation&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0.2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; ease-in&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0.4&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;s&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-constant z-property-value&quot;&gt; forwards&lt;&#x2F;span&gt;&lt;span class=&quot;z-meta z-property-value&quot;&gt; fade&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;  width&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-other z-unit&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation z-definition z-keyword z-keyword z-control&quot;&gt;@&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-control z-at-rule z-keyword z-control&quot;&gt;keyframes&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; fade&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;  0%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    opacity&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-source z-css&quot;&gt;  100%&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-type z-property-name&quot;&gt;    opacity&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I use CSS animations instead of JavaScript.&lt;br &#x2F;&gt;
The duration of the animation is based on the 95% percentile load time of all visitors of the page. Although it’s just an approximation, this should work for most readers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;result&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#result&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Result&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;No JavaScript needed&lt;&#x2F;li&gt;
&lt;li&gt;Works on all modern browsers&lt;&#x2F;li&gt;
&lt;li&gt;Supports a fallback in case the main image can’t be loaded&lt;&#x2F;li&gt;
&lt;li&gt;Tiny overhead&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;resources&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#resources&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Resources&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.guypo.com&#x2F;introducing-lqip-low-quality-image-placeholders&quot;&gt;Introducing LQIP – Low Quality Image Placeholders&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;jmperezperez.com&#x2F;medium-image-progressive-loading-placeholder&#x2F;&quot;&gt;How Medium does progressive image loading&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;axe312ger&#x2F;sqip&quot;&gt;SQIP, a new preview technique using pure SVG&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Go vs Rust? Choose Go.</title>
        <published>2017-09-15T00:00:00+00:00</published>
        <updated>2021-04-29T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/go-vs-rust/"/>
        <id>https://endler.dev/2017/go-vs-rust/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/go-vs-rust/">&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;go-vs-rust&amp;#x2F;hero.svg&quot; 
        
            alt=&quot;Gopher designed with &amp;lt;a href=&amp;#x27;https:&amp;#x2F;&amp;#x2F;gopherize.me&amp;#x27;&amp;gt;Gopherize.me&amp;lt;&amp;#x2F;a&amp;gt;. Gears designed by &amp;lt;a href=&amp;#x27;https:&amp;#x2F;&amp;#x2F;www.freepik.com&amp;#x2F;free-vector&amp;#x2F;gear-background-with-pieces-different-colors_966124.htm&amp;#x27;&amp;gt;Freepik&amp;lt;&amp;#x2F;a&amp;gt;.&quot;
        

        

        
        
        
            width=&quot;809&quot;
        
        
            height=&quot;400&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            
            
            Source: Gopher designed with &lt;a href=&#x27;https:&#x2F;&#x2F;gopherize.me&#x27;&gt;Gopherize.me&lt;&#x2F;a&gt;. Gears designed by &lt;a href=&#x27;https:&#x2F;&#x2F;www.freepik.com&#x2F;free-vector&#x2F;gear-background-with-pieces-different-colors_966124.htm&#x27;&gt;Freepik&lt;&#x2F;a&gt;.
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;&lt;div class=&quot;info&quot;&gt;
  &lt;p&gt;I wrote this article a long time ago. In the meantime,
my opinion on some aspects has changed.&lt;&#x2F;p&gt;
&lt;p&gt;In order to give a more balanced perspective on the pros and cons, I suggest to
read this comparison on Go vs Rust instead, which I wrote in collaboration with
Shuttle 🚀&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.shuttle.rs&#x2F;blog&#x2F;2023&#x2F;09&#x2F;27&#x2F;rust-vs-go-comparison&quot;&gt;Rust vs Go: A Hands-On Comparison&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;&#x2F;div&gt;
&lt;p&gt;“Rust or Go, which one should I choose?” is a question I get quite often.
Both languages seem to be competing for the same user base and they both seem to be
&lt;em&gt;systems programming&lt;&#x2F;em&gt; languages, so there must be a clear winner, right?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;go-practical-pragmatic-plain&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#go-practical-pragmatic-plain&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Go: practical, pragmatic, plain&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;go-vs-rust&amp;#x2F;go.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;go-vs-rust&amp;#x2F;go.jpg&quot; 
        
            alt=&quot;The Golang learning curve over time, a straight line.&quot;
        

        

        
        
        
            width=&quot;504&quot;
        
        
            height=&quot;412&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            The Golang learning curve over time, a straight line.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;I don’t think Go is an elegant language. Its biggest feature is &lt;del&gt;simplicity&lt;&#x2F;del&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=SxdOUGdseq4&quot;&gt;easiness&lt;&#x2F;a&gt;.
Go is not even a systems programming language. While it’s great for writing microservices and tooling around backend infrastructure, I would not want to write a kernel or a memory allocator with it.&lt;&#x2F;p&gt;
&lt;p&gt;But with Go, you &lt;em&gt;get things done&lt;&#x2F;em&gt; — fast.&lt;br &#x2F;&gt;
Go is one of the most productive languages I’ve ever worked with.
The mantra is: solve real problems today.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;rust-s-strong-guarantees-come-at-a-cost&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#rust-s-strong-guarantees-come-at-a-cost&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Rust’s strong guarantees come at a cost&lt;&#x2F;h2&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;go-vs-rust&amp;#x2F;rust.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;go-vs-rust&amp;#x2F;rust.jpg&quot; 
        
            alt=&quot;The Rust learning curve over time, a bumpy ride.&quot;
        

        

        
        
        
            width=&quot;505&quot;
        
        
            height=&quot;419&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            The Rust learning curve over time, a bumpy ride.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Rust in comparison is &lt;strong&gt;hard&lt;&#x2F;strong&gt;. It took me many months to become somewhat productive.
You need to invest a serious amount of time to see any benefit.
Rust is already a powerful language and it gets stronger every day.
It feels much more like a &lt;em&gt;pragmatic Haskell&lt;&#x2F;em&gt; to me than a &lt;em&gt;safer C&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Don’t get me wrong: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;channel&#x2F;UCZ_EWaQZCZuGGfnuqUoHujw&quot;&gt;I love Rust&lt;&#x2F;a&gt;, and it helped me become a better programmer. It is certainly a nice language to learn. The big question is, if it is the right choice for your next major project.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s the thing: if you choose Rust, usually you need the guarantees, that the language provides:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Safety against &lt;code&gt;Null&lt;&#x2F;code&gt; pointers, race conditions and all sorts of low-level threats.&lt;&#x2F;li&gt;
&lt;li&gt;Predictable runtime behavior (zero cost abstractions and no garbage collector).&lt;&#x2F;li&gt;
&lt;li&gt;(Almost) total control over the hardware (memory layout, processor features).&lt;&#x2F;li&gt;
&lt;li&gt;Seamless interoperability with other languages.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you don’t &lt;em&gt;require&lt;&#x2F;em&gt; any of these features, Rust might be a poor choice for your next project.
That’s because these guarantees come with a cost: ramp-up time.
You’ll need to unlearn bad habits and learn new concepts.
Chances are, you will &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;m-decoster.github.io&#x2F;2017&#x2F;01&#x2F;16&#x2F;fighting-borrowchk&#x2F;&quot;&gt;fight with the borrow checker&lt;&#x2F;a&gt; a lot when you start out.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;case-study-primality-by-trial-division&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#case-study-primality-by-trial-division&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Case-study: Primality by trial division&lt;&#x2F;h2&gt;
&lt;p&gt;Let’s say, you want to check if a number is &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Prime_number&quot;&gt;prime&lt;&#x2F;a&gt;.
The easiest way is to check if we can divide the number by any smaller natural number (without a remainder). If not, we found a prime number! This approach is called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Trial_division&quot;&gt;trial division&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here’s how to do that in Golang (courtesy of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rosettacode.org&#x2F;wiki&#x2F;Primality_by_trial_division#Go&quot;&gt;Rosetta Code&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;func&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; IsPrime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-numeric z-go&quot;&gt; int&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-boolean z-go&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;		n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	switch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	case&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;		return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	default&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;		for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; :=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; &amp;lt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;++&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;			if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;%&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;i&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;				return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;			}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;		}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;	}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;	return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here’s the same thing in Rust:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;pub&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; is_prime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;        0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;            for&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword&quot;&gt; in&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;                if&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;                    return&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;                }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-language&quot;&gt;            true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;At first sight, both solutions look pretty similar.
But if we look closer, we can spot some differences.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;In Go, we use a simple switch-case statement. In Rust, we use a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;1.2.0&#x2F;book&#x2F;match.html&quot;&gt;&lt;code&gt;match&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; statement, which is much more powerful.&lt;&#x2F;li&gt;
&lt;li&gt;In Go, we use a simple for-loop to iterate over the numbers 2 to n. In Rust, we use a range expression (&lt;code&gt;2..n&lt;&#x2F;code&gt;).&lt;&#x2F;li&gt;
&lt;li&gt;In Go, we use two &lt;code&gt;return&lt;&#x2F;code&gt; statements, in Rust we have one &lt;code&gt;return&lt;&#x2F;code&gt; &lt;em&gt;expression&lt;&#x2F;em&gt;. In general, most things in Rust are expressions, which can be returned and assigned to a variable. Read more about expressions &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;beta&#x2F;reference&#x2F;expressions.html&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;In many areas, Rust is more functional than Golang. You could rewrite the above code using the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;std&#x2F;iter&#x2F;trait.Iterator.html#method.any&quot;&gt;&lt;code&gt;any&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; method, which is implemented for &lt;code&gt;Range&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;fn&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; is_prime&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;:&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; u64&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; -&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; bool&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;    match&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;        0&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;...&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;1&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; false&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;        _&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&amp;gt;&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt;2&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;..&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;n&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;any&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;|&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; n&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; %&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; d&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-numeric&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It might seem a little alien at first, but it will become second-nature after a while.&lt;&#x2F;p&gt;
&lt;p&gt;This was just a quick example, of course. I suggest, you browse some code on &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rosettacode.org&#x2F;wiki&#x2F;Rosetta_Code&quot;&gt;Rosetta Code&lt;&#x2F;a&gt; to get a better feeling for both languages.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;case-study-finding-duplicate-words-in-text-files&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#case-study-finding-duplicate-words-in-text-files&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Case study: Finding duplicate words in text files&lt;&#x2F;h2&gt;
&lt;p&gt;If you’re more like a visual type, here is a video where I write a simple
concurrent program in Go and Rust to compare both languages:&lt;&#x2F;p&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;css&#x2F;video.css&quot; &#x2F;&gt;
&lt;script defer src=&quot;&#x2F;video.js&quot;&gt;&lt;&#x2F;script&gt;
&lt;div 
  class=&quot;light-video-embed&quot; 
  data-url=&quot;https:&amp;#x2F;&amp;#x2F;www.youtube.com&amp;#x2F;embed&amp;#x2F;B5xYBrxVSiE&quot;
  
&gt; 
  &lt;picture&gt;
    &lt;source srcset=&quot;maxresdefault.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    &lt;img src=&quot;maxresdefault.jpg&quot;
    
    
    
    
     
    
    
    &#x2F;&gt;
  &lt;&#x2F;picture&gt;
  &lt;div class=&quot;play&quot;&gt;&lt;&#x2F;div&gt;
&lt;&#x2F;div&gt;

&lt;script&gt;
  document.addEventListener(&quot;DOMContentLoaded&quot;, function() {
    lightEmbedInit();
  });
&lt;&#x2F;script&gt;
&lt;h2 id=&quot;some-things-i-prefer-in-go&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#some-things-i-prefer-in-go&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Some things I prefer in Go&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Fast compile times&lt;&#x2F;li&gt;
&lt;li&gt;Pragmatic problem-solving approach&lt;&#x2F;li&gt;
&lt;li&gt;Nice ecosystem for typical &lt;em&gt;DevOps&lt;&#x2F;em&gt; tasks&lt;&#x2F;li&gt;
&lt;li&gt;Batteries-included standard-library&lt;&#x2F;li&gt;
&lt;li&gt;IDE support&lt;&#x2F;li&gt;
&lt;li&gt;Simple error handling&lt;&#x2F;li&gt;
&lt;li&gt;The mascot 😉&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;some-things-i-prefer-in-rust&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#some-things-i-prefer-in-rust&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Some things I prefer in Rust&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Safety: No null pointers, no data races,…&lt;&#x2F;li&gt;
&lt;li&gt;Fine-grained system control&lt;&#x2F;li&gt;
&lt;li&gt;Incredible runtime speed (comparable with C&#x2F;C++)&lt;&#x2F;li&gt;
&lt;li&gt;Zero-cost abstractions&lt;&#x2F;li&gt;
&lt;li&gt;Awesome, open-minded community&lt;&#x2F;li&gt;
&lt;li&gt;Simple package management with cargo&lt;&#x2F;li&gt;
&lt;li&gt;Support for Generics in form of traits&lt;&#x2F;li&gt;
&lt;li&gt;C interop and FFI&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#conclusion&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Conclusion&lt;&#x2F;h2&gt;
&lt;p&gt;99% of the time, Go is “good enough” and that 1% where it isn’t, you’ll know.
And then take a look at Rust, because the two languages complement each other pretty well.
If you’re interested in &lt;strong&gt;hands-on Rust consulting&lt;&#x2F;strong&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;sponsors&#x2F;mre?frequency=one-time&amp;amp;sponsor=mre&quot;&gt;pick a date from my
calendar&lt;&#x2F;a&gt; and we can talk about how I can help.&lt;&#x2F;p&gt;
&lt;p&gt;After all is said and done, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dave.cheney.net&#x2F;2015&#x2F;07&#x2F;02&#x2F;why-go-and-rust-are-not-competitors&quot;&gt;Rust and Go are not really competitors&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Afraid of Makefiles? Don&#x27;t be!</title>
        <published>2017-08-15T00:00:00+00:00</published>
        <updated>2022-03-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/makefiles/"/>
        <id>https://endler.dev/2017/makefiles/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/makefiles/">&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;makefiles&amp;#x2F;clothes.svg&quot; 
        
            alt=&quot;What do clothes have to do with Makefiles? Find out in this post!&quot;
        

        

        
        
        
            width=&quot;1232&quot;
        
        
            height=&quot;563&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            What do clothes have to do with Makefiles? Find out in this post!
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freepik.com&#x2F;free-photos-vectors&#x2F;background&quot;&gt;Illustration by Anindyanfitri - Freepik.com&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In the last few years, I’ve had the pleasure to work with a lot of talented Software Engineers.
One thing that struck me is that many of them did not have any working knowledge of &lt;code&gt;Makefiles&lt;&#x2F;code&gt;
and why they are useful.&lt;&#x2F;p&gt;
&lt;p&gt;When faced with the task to automate a build process, they often roll their own shell scripts.
Common culprits are called &lt;code&gt;build.sh&lt;&#x2F;code&gt;, &lt;code&gt;run.sh&lt;&#x2F;code&gt; or &lt;code&gt;doall.sh&lt;&#x2F;code&gt; in a project folder.&lt;&#x2F;p&gt;
&lt;p&gt;They implement the same basic functionality over and over again:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Parsing input parameters and environment variables.&lt;&#x2F;li&gt;
&lt;li&gt;Manually managing dependencies between build steps.&lt;&#x2F;li&gt;
&lt;li&gt;Error handling (…maybe).&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Along the way, they keep making the same basic mistakes:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Incorrectly handling &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.pixelbeat.org&#x2F;programming&#x2F;shell_script_mistakes.html&quot;&gt;input parameters&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Shellshock_(software_bug)&quot;&gt;environment variables&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Missing dependencies between build steps.&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.davidpashley.com&#x2F;articles&#x2F;writing-robust-shell-scripts&#x2F;&quot;&gt;Forgetting to handle errors&lt;&#x2F;a&gt; and — even worse — carrying on with the program execution.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;These are issues Makefiles were invented to solve.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;makefiles-are-scary&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#makefiles-are-scary&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Makefiles are scary!&lt;&#x2F;h2&gt;
&lt;p&gt;If you think that &lt;code&gt;make&lt;&#x2F;code&gt; is scary, you probably think of complicated build machinery for &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;community.kde.org&#x2F;Guidelines_and_HOWTOs&#x2F;Build_from_source&quot;&gt;big&lt;&#x2F;a&gt; &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;chromium.googlesource.com&#x2F;chromium&#x2F;src&#x2F;+&#x2F;master&#x2F;docs&#x2F;linux&#x2F;build_instructions.md&quot;&gt;software&lt;&#x2F;a&gt; projects.
It doesn’t need to be that way. Let’s hear from the author of &lt;code&gt;make&lt;&#x2F;code&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Stuart_Feldman&quot;&gt;Stuart Feldman&lt;&#x2F;a&gt; himself:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;It began with an elaborate idea of a dependency analyzer, boiled down to something much simpler, and turned into Make that weekend. Use of tools that were still wet was part of the culture. Makefiles were text files, not magically encoded binaries because &lt;strong&gt;that was the Unix ethos: printable, debuggable, understandable stuff.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;— &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nakamotoinstitute.org&#x2F;static&#x2F;docs&#x2F;taoup.pdf&quot;&gt;The Art of Unix Programming (2003)&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Make was built in &lt;em&gt;one weekend&lt;&#x2F;em&gt; to solve a reoccuring problem in a simple way.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;makefiles-are-simple&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#makefiles-are-simple&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Makefiles are simple!&lt;&#x2F;h2&gt;
&lt;p&gt;Before I leave the house, I need to get dressed.
I use the same simple routine every time:
Underpants, trousers, shirt, pullover, socks, shoes, jacket.
Most likely you also have a routine, even though yours might be different.&lt;&#x2F;p&gt;
&lt;p&gt;Some of these steps depend on each other.&lt;br &#x2F;&gt;
&lt;code&gt;Make&lt;&#x2F;code&gt; is useful for handling dependencies.&lt;br &#x2F;&gt;
Let’s try to express my routine as a &lt;code&gt;Makefile&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;make&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;dress&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; trousers shoes jacket&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control z-\40  z-keyword z-control&quot;&gt;	@&lt;&#x2F;span&gt;&lt;span&gt;echo &amp;quot;All done. Let&amp;#39;s go outside!&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;jacket&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; pullover&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control z-\40  z-keyword z-control&quot;&gt;	@&lt;&#x2F;span&gt;&lt;span&gt;echo &amp;quot;Putting on jacket.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;pullover&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; shirt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control z-\40  z-keyword z-control&quot;&gt;	@&lt;&#x2F;span&gt;&lt;span&gt;echo &amp;quot;Putting on pullover.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;shirt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control z-\40  z-keyword z-control&quot;&gt;	@&lt;&#x2F;span&gt;&lt;span&gt;echo &amp;quot;Putting on shirt.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;trousers&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; underpants&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control z-\40  z-keyword z-control&quot;&gt;	@&lt;&#x2F;span&gt;&lt;span&gt;echo &amp;quot;Putting on trousers.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;underpants&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control z-\40  z-keyword z-control&quot;&gt;	@&lt;&#x2F;span&gt;&lt;span&gt;echo &amp;quot;Putting on underpants.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;shoes&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; socks&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control z-\40  z-keyword z-control&quot;&gt;	@&lt;&#x2F;span&gt;&lt;span&gt;echo &amp;quot;Putting on shoes.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;socks&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; pullover&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-control z-\40  z-keyword z-control&quot;&gt;	@&lt;&#x2F;span&gt;&lt;span&gt;echo &amp;quot;Putting on socks.&lt;&#x2F;span&gt;&lt;span&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If we execute the &lt;code&gt;Makefile&lt;&#x2F;code&gt;, we get the following output:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ make dress&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Putting on underpants.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Putting on trousers.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Putting on shirt.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Putting on pullover.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Putting on socks.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Putting on shoes.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Putting on jacket.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;All done. Let&amp;#39;s go outside!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;what-just-happened&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-just-happened&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;What just happened?&lt;&#x2F;h2&gt;
&lt;p&gt;Noticed how the steps are in the correct order?
By plainly writing down the dependencies between the steps, &lt;code&gt;make&lt;&#x2F;code&gt; helps us to execute them correctly.&lt;&#x2F;p&gt;
&lt;p&gt;Each build step has the following structure:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;make&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;target&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; [dependencies]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;lt;shell command to execute&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;lt;shell command to execute&lt;&#x2F;span&gt;&lt;span&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	..&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The first target in a &lt;code&gt;Makefile&lt;&#x2F;code&gt; will be executed by default when we call &lt;code&gt;make&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;The order of the targets does not matter.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Shell commands must be indented with a tab.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Add an &lt;code&gt;@&lt;&#x2F;code&gt; sign to suppress output of the command that is executed.&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;If &lt;code&gt;target&lt;&#x2F;code&gt; isn’t a file you want to build, please add &lt;code&gt;.PHONY &amp;lt;target&amp;gt;&lt;&#x2F;code&gt; at the end of the build step.
Common phony targets are: clean, install, run,…
Otherwise, if somebody creates an &lt;code&gt;install&lt;&#x2F;code&gt; directory, &lt;code&gt;make&lt;&#x2F;code&gt; will silently fail, because the build target already exists.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;make&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;.PHONY&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;span&gt; install&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;install&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	npm instal&lt;&#x2F;span&gt;&lt;span&gt;l&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Congratulations! You’ve learned 90% of what you need to know about &lt;code&gt;make&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#next-steps&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Next steps&lt;&#x2F;h2&gt;
&lt;p&gt;Real &lt;code&gt;Makefiles&lt;&#x2F;code&gt; can do much more! They will &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;3798609&#x2F;270334&quot;&gt;only build the files that have changed&lt;&#x2F;a&gt; instead of doing a full rebuild.
And they will do &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;a&#x2F;3841803&#x2F;270334&quot;&gt;as much as possible in parallel&lt;&#x2F;a&gt;.
Just try to keep them simple please.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Of Boxes and Trees - Smart Pointers in Rust</title>
        <published>2017-08-12T00:00:00+00:00</published>
        <updated>2020-04-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/boxes-and-trees/"/>
        <id>https://endler.dev/2017/boxes-and-trees/</id>
        
        <summary type="html">&lt;p&gt;Recently, I tried to implement a binary tree data structure in Rust.
Each binary tree has a root value, a left, and a right subtree.
I started from this Python implementation, which is quite straightforward.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Why Type Systems Matter</title>
        <published>2017-07-10T00:00:00+00:00</published>
        <updated>2017-07-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/why-type-systems-matter/"/>
        <id>https://endler.dev/2017/why-type-systems-matter/</id>
        
        <summary type="html">&lt;p&gt;I’ve written most of my code in dynamically typed languages such as Python or PHP; but ever since dabbling with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.rust-lang.org&quot;&gt;Rust&lt;&#x2F;a&gt;, I’ve developed a passion for static type systems.&lt;br &#x2F;&gt;
It began to feel very natural to me; like a totally new way to express myself.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Being a Professional Programmer</title>
        <published>2017-05-18T00:00:00+00:00</published>
        <updated>2017-05-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/professional-programming/"/>
        <id>https://endler.dev/2017/professional-programming/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/professional-programming/">&lt;p&gt;When I was around 12, I set myself the goal to become a professional programmer.&lt;br &#x2F;&gt;
I can tell, because at this time I made the conscious decision to use my right hand to control the mouse — even though I’m left-handed.&lt;&#x2F;p&gt;
&lt;p&gt;My reasoning was, that if I ever had to help out a colleague with a computer problem I sure did not want to move her mouse to the other side before getting started. That would be awkward.
(Of course I did not foresee the advent of the wireless mouse… As a matter of fact, I still use the right hand out of habit.)&lt;&#x2F;p&gt;
&lt;p&gt;One thing I always wanted to know is how a typical workday of a programmer looked like.
Was I wasting my time by pursuing this career?
Only later I found the answer — but I had to become a professional programmer myself.
This article aims to save you from a few years of uncertainty.&lt;&#x2F;p&gt;
&lt;p&gt;Before you dig into this, be sure to read the first part of this series titled &lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;why-i-love-programming&#x2F;&quot;&gt;“Why I love Programming”&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-the-difference-between-professional-and-hobby-programming&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-s-the-difference-between-professional-and-hobby-programming&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;What’s the difference between “professional” and “hobby” programming?&lt;&#x2F;h2&gt;
&lt;p&gt;In one word: &lt;em&gt;accountability&lt;&#x2F;em&gt;.&lt;br &#x2F;&gt;
You are expected to be responsible.&lt;&#x2F;p&gt;
&lt;p&gt;Programming in your free time is like throwing a party without having to clean up: pure fun!
If you get bored you’re free to move on.
Not so in professional programming, where you’re expected to get the job done.&lt;&#x2F;p&gt;
&lt;p&gt;Every application requires constant bug fixing, refactoring and sometimes even monkey patching. Maintaining code is no amusement park; especially if it’s not your own.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;being-a-junior-developer&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#being-a-junior-developer&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Being a Junior Developer&lt;&#x2F;h2&gt;
&lt;p&gt;Fresh out of school you might think you’re a pretty kick-ass programmer. Let me tell you: you’re not.
You wouldn’t guess what talented people can do with these blinking machines.
You’ll have tons of things to learn in the first few years.&lt;&#x2F;p&gt;
&lt;p&gt;Professional software development is a lengthy process. Writing readable, well-tested, well-documented code is a substantial effort. You will need patience, lots of it. Both, with yourself and with others.&lt;&#x2F;p&gt;
&lt;p&gt;As a junior, you only think in black and white. You look at some code, and it’s all wrong. Who in their right mind created this horrible monstrosity?!
As you become more experienced, you’ll see the shades of grey.&lt;&#x2F;p&gt;
&lt;p&gt;Eventually, you’ll understand that those neckbeards were not slower than you, but
more careful. You learn how to test your code, how to document it. You even begin to
appreciate UML diagrams.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;becoming-obsolete&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#becoming-obsolete&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Becoming obsolete&lt;&#x2F;h2&gt;
&lt;p&gt;“The world is moving too fast. What you learned today is obsolete tomorrow. Why bother?”.
I’ve heard that saying countless times throughout my career.
It’s both, popular and wrong.&lt;&#x2F;p&gt;
&lt;p&gt;If a skill becomes obsolete, it’s not a skill.
Throughout your career you don’t want to be known as “the Jenkins guy”, you want to be the
expert in Software Quality. Hint: If you don’t know what Jenkins is, that’s the
whole point. You should not narrow down your scope too much.
The right skills never become obsolete.&lt;&#x2F;p&gt;
&lt;p&gt;From time to time it happens, that due to some new company policy your beautiful creation will become obsolete.
As depressing as it sounds: it’s a regular part of the software business.
You need to adapt.
One advice I can give you is not to take it too seriously.
Drop the project, keep the wisdom.
Embrace change.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;writing-software-in-a-non-perfect-world&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#writing-software-in-a-non-perfect-world&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Writing software in a non-perfect world&lt;&#x2F;h2&gt;
&lt;p&gt;A professional programmer has to deal with deficiencies all the time. The game is called “balancing constraints”. Deadlines, budgets, and code quality are just a few competing constraints we have to consider.
Elegant designs fade away in the face of reality.
In the end you want to earn money with your software, so you have to ship it!&lt;&#x2F;p&gt;
&lt;p&gt;The best developers I know, keep the balance between pragmatism and elegance.
They know which parts matter and which don’t. Those who don’t will be replaced
when there’s a need.&lt;&#x2F;p&gt;
&lt;p&gt;For me, I was always leaning more towards elegance.
That’s just a nicer way to say I was a perfectionist.
I needed to learn the pragmatic part through hard work.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;mentoring-less-experienced-programmers&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#mentoring-less-experienced-programmers&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Mentoring less experienced Programmers&lt;&#x2F;h2&gt;
&lt;blockquote&gt;
&lt;p&gt;The better you become at programming, the less you code.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Instead, you will spend more time thinking about Software Architecture,
high-level designs and splitting up the work into smaller junks for other developers to consume.
You will start mentoring Junior Developers. Recruiting will require a lot of your
attention. You will spend your time in Meetings, discussing project goals with
business people.
One might say, you take the role of a mediator. Others might call you a manager.&lt;&#x2F;p&gt;
&lt;p&gt;Once you know the ins and outs of the business, you are an essential asset for
the company. You might get asked to become a manager, or at least managing projects will slowly feel like a natural extension of your responsibilities.
But beware! This slow and gradual process is dangerous.
Moving back to being a full-time programmer is not easy.
During the time you were busy with project management, others were busy improving their
coding skills.
You can try to keep up-to-date in your free time but that’s hard.&lt;&#x2F;p&gt;
&lt;p&gt;I’ve seen excellent developers become great managers. At some point in your career
it’s a decision you need to make for yourself.&lt;&#x2F;p&gt;
&lt;p&gt;However you decide, it pays off to invest some time into learning how to
communicate. Empathy plays a prominent role in that.
Developing software as a team is so complicated that a lot of time is spent on aligning goals and communicating problems. In fact, communication is what you get paid for. This includes documentation, tests and the code itself.&lt;&#x2F;p&gt;
&lt;p&gt;Talk to others, listen to their problems. Read books about Software Project
Management, even though you don’t want to be a manager yourself. It will help
you understand the role of your boss.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-word-about-money&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a-word-about-money&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;A word about money&lt;&#x2F;h2&gt;
&lt;p&gt;There are many good reasons to work in IT, but money is not one of them.&lt;&#x2F;p&gt;
&lt;p&gt;While it can be tempting to base your career decisions on prospective salary,
don’t do it. You will be very unhappy. You will spend eight hours or more each day sitting in front of a blinking cursor.
That’s a lot of time, and time is much more valuable than money.&lt;&#x2F;p&gt;
&lt;p&gt;Don’t get me wrong. There’s plenty of jobs that pay well.
You will most likely not get rich, though. If you want
to make it big, I can’t help you. Maybe look into Real Estate or so…
The only way to get rich as a developer is to work on something really hard, put in lots of hours and get
lucky. Startups, basically. Keep in mind: One Bill Gates takes a thousand failed
attempts.
Another way is to stop being a programmer and become a manager instead.
I’ve already shared my opinion on that in the last section.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-words&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#final-words&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Final words&lt;&#x2F;h2&gt;
&lt;p&gt;While you should learn to read (and maybe write) code, working as a professional programmer is not for everyone.
You might ask: “Is it worth it?”.
For me it was the right decision. Hopefully I could help you to make your own.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Future of Rust</title>
        <published>2017-04-27T00:00:00+00:00</published>
        <updated>2017-04-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/future-of-rust/"/>
        <id>https://endler.dev/2017/future-of-rust/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/future-of-rust/">&lt;p&gt;Let me first point out the obvious: yes, the title is a little sensationalist. Also
you might be asking why I should be entitled to talk about the future of Rust. After
all, I’m neither part of the Rust core team, nor a major contributor to the Rust
ecosystem. To that I answer: why not? It’s fun to think about the future of
systems programming in general and Rust in particular.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;future-of-rust&amp;#x2F;crab.svg&quot; 
        
            alt=&quot;Ferris is the inofficial Rust mascot&quot;
        

        

        
        
        
            width=&quot;639&quot;
        
        
            height=&quot;429&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            Ferris is the inofficial Rust mascot
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: Illustration provided by &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.freepik.com&quot;&gt;FreePik.com&lt;&#x2F;a&gt;
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;You might have heard of the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;internals.rust-lang.org&#x2F;t&#x2F;setting-our-vision-for-the-2017-cycle&#x2F;3958&quot;&gt;near-term goals&lt;&#x2F;a&gt; that the core team has committed itself to. Faster compile times and a more gentle learning curve come to mind.
This post is not about that.
Instead, I want to explore some more exotic areas where Rust could shine in
five to ten years from now. To make it big, we need both, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.goodreads.com&#x2F;quotes&#x2F;726646-there-are-two-things-children-should-get-from-their-parents&quot;&gt;roots and wings&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;data-science&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#data-science&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Data Science&lt;&#x2F;h2&gt;
&lt;p&gt;Right now, the most popular languages for Data Science are Python, Java, R, and C++.&lt;&#x2F;p&gt;
&lt;figure&gt;
  &lt;img src=&quot;&#x2F;2017&#x2F;future-of-rust&#x2F;data-science-languages.png&quot; alt=&quot;Programming language popularity for data science&quot; &#x2F;&gt;
  &lt;figcaption&gt;Programming language popularity for data science (&lt;a href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20170311030523&#x2F;https:&#x2F;&#x2F;www.ibm.com&#x2F;developerworks&#x2F;community&#x2F;blogs&#x2F;jfp&#x2F;entry&#x2F;What_Language_Is_Best_For_Machine_Learning_And_Data_Science?lang=en&quot;&gt;Source&lt;&#x2F;a&gt;).
  &lt;&#x2F;figcaption&gt;
&lt;&#x2F;figure&gt;
&lt;p&gt;We’ve observed that while prototypes are mostly written in dynamically typed
languages like Python and R, once an algorithm reaches production level quality
it is often &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20170311030523&#x2F;https:&#x2F;&#x2F;www.ibm.com&#x2F;developerworks&#x2F;community&#x2F;blogs&#x2F;jfp&#x2F;entry&#x2F;What_Language_Is_Best_For_Machine_Learning_And_Data_Science?lang=en&quot;&gt;rewritten in faster languages such as C++&lt;&#x2F;a&gt; for scalability.
It is not unthinkable that Rust is going to be some healthy competition for C++ in the near future.
The benchmarks of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;autumnai&#x2F;leaf&quot;&gt;leaf&lt;&#x2F;a&gt;, a machine learning library written in Rust, are already nothing short of
impressive.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;blockbuster-games&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#blockbuster-games&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Blockbuster games&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;rust_gamedev&#x2F;comments&#x2F;4qlftu&#x2F;look_our_game_writen_entirely_in_rust&#x2F;d4tz4r3&#x2F;&quot;&gt;Games&lt;&#x2F;a&gt; are another area where Rust might shine.
It’s financially attractive for Game Studios to support multiple platforms without much
effort. &lt;code&gt;Cargo&lt;&#x2F;code&gt; and &lt;code&gt;rustup&lt;&#x2F;code&gt; make cross-compiling easy.
Modern libraries slowly fill the tooling gaps for large-scale game development.
&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tomaka&#x2F;vulkano&quot;&gt;Rust’s support for the Vulkan 3D graphics API&lt;&#x2F;a&gt; might already be the best of class.
The killer feature though is the unique combination of safety and performance.
If you ship a game to a million players and they throw money at you, you’ll better make sure that it doesn’t crash… &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;gamingbolt.com&#x2F;15-buggiest-games-ever-released&quot;&gt;right?&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;That said, the first AAA Rust game might still be far in the future. &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=Az5F4lwSljI&amp;amp;feature=youtu.be&amp;amp;t=23m50s&quot;&gt;Here’s Blizzard’s standpoint on Rust in 2017&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;systems-engineering&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#systems-engineering&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Systems Engineering&lt;&#x2F;h2&gt;
&lt;p&gt;Maybe — eventually — we will also see formal verification of the Rust core. Projects like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;plv.mpi-sws.org&#x2F;rustbelt&#x2F;&quot;&gt;RustBelt&lt;&#x2F;a&gt; would then open new opportunities in safety-focused industries like the Space industry. Wouldn’t it be nice to safely land a Spacecraft on Mars that is controlled by Rust? (Or by one of its spiritual successors.)
I wonder if &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.spacex.com&#x2F;&quot;&gt;SpaceX&lt;&#x2F;a&gt; is experimenting with Rust already…&lt;&#x2F;p&gt;
&lt;h2 id=&quot;integrating-with-other-languages&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#integrating-with-other-languages&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Integrating with other languages&lt;&#x2F;h2&gt;
&lt;p&gt;There are many other areas I haven’t even mentioned yet. For example, financial and medical software or Scientific Computing, just to name a few.
In all cases, Rust might be a good fit. Right now the biggest barrier to entry
is probably the huge amount of legacy code. Many industries maintain large codebases in Cobol,
C or Fortran that are not easily rewritten.&lt;&#x2F;p&gt;
&lt;p&gt;Fortunately, Rust has been proven to work very nicely with other languages.
Partly because of strong C-compatibility and partly because there is no Runtime or Garbage Collector.
A typical pattern is to optimize some core part of an application in Rust that has hard safety&#x2F;performance
requirements, while leaving the rest untouched.
I think this symbiosis will only become stronger in the long run.
There are even ambitious projects like &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;archive.fosdem.org&#x2F;2017&#x2F;schedule&#x2F;event&#x2F;mozilla_translation_from_c_to_rust&#x2F;&quot;&gt;Corrode&lt;&#x2F;a&gt; which attempt to translate C code to Rust automatically.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#summary&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Summary&lt;&#x2F;h2&gt;
&lt;p&gt;Overall I see huge potential for Rust in areas where safety, performance or total control over the machine are essential. With languages like Rust and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;crystal-lang.org&#x2F;&quot;&gt;Crystal&lt;&#x2F;a&gt;, a whole class of errors is a thing of the past. No null pointers, no segmentation faults, no memory leaks, no data races.
I find it encouraging that future generations of programmers will take all that for granted.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Launching a URL Shortener in Rust using Rocket</title>
        <published>2017-04-09T00:00:00+00:00</published>
        <updated>2020-08-26T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/rust-url-shortener/"/>
        <id>https://endler.dev/2017/rust-url-shortener/</id>
        
        <summary type="html">&lt;p&gt;One common systems design task in interviews is to sketch the software architecture of a URL shortener (a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;bitly.com&#x2F;&quot;&gt;bit.ly&lt;&#x2F;a&gt; clone, if you may).
Since I was playing around with &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;rocket.rs&#x2F;&quot;&gt;Rocket&lt;&#x2F;a&gt; – a web framework for Rust – why not give it a try?&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>The Essence of Information</title>
        <published>2017-03-18T00:00:00+00:00</published>
        <updated>2017-03-18T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/the-essence-of-information/"/>
        <id>https://endler.dev/2017/the-essence-of-information/</id>
        
        <content type="html" xml:base="https://endler.dev/2017/the-essence-of-information/">&lt;p&gt;People look confused when I tell them about my passion for algorithms and data-structures.
Most of them understand what a Programmer is doing, but not what Computer Science is good for.
And even if they do, they think it has no practical relevance.
Let me show you with a simple example, that applied Computer Science can be found everywhere.&lt;&#x2F;p&gt;
&lt;p&gt;Imagine a pile of socks that need to get sorted.
Not exactly the most exciting pastime.
You’ve put off this task for so long, that it will inevitably take an hour to be done.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;the-essence-of-information&amp;#x2F;big_pile.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;the-essence-of-information&amp;#x2F;big_pile.jpg&quot; 
        
            alt=&quot;Yes, there is a game about sorting socks.&quot;
        

        

        
        
        
            width=&quot;590&quot;
        
        
            height=&quot;391&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            Yes, there is a game about sorting socks.
            
            
            &lt;br &#x2F;&gt;
            
            
            Source: It’s called &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;apps.apple.com&#x2F;app&#x2F;sort-the-socks&#x2F;id438108346&quot;&gt;Sort the Socks&lt;&#x2F;a&gt; and you can get it for free on the App Store.
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Considering your options, you decide to get some help.
Together with a friend you get to work. You finish in roughly half the time.&lt;&#x2F;p&gt;
&lt;p&gt;A Computer Scientist might call this pile of socks a &lt;em&gt;resource&lt;&#x2F;em&gt;.
You and your friend get bluntly degraded to &lt;em&gt;workers&lt;&#x2F;em&gt;.
Both of you can work on the problem at the same time — or &lt;em&gt;in parallel&lt;&#x2F;em&gt;.
This is the gist of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Parallel_computing&quot;&gt;Parallel Computing&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now, some properties make sock-sorting a good fit for doing in parallel.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The work can be nicely split up. It takes about the same time for every worker to find a pair of socks.&lt;&#x2F;li&gt;
&lt;li&gt;Finding a different pair is a completely separate task that can happen at the same time.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;The more workers you assign to this task, the faster you’re done.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;1 worker takes 60 minutes.&lt;&#x2F;li&gt;
&lt;li&gt;2 workers take 30 minutes.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;How long will 3 workers take? Right! Around 20 minutes. We could write down
a simple formula for this relationship:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;the-essence-of-information&amp;#x2F;equation.svg&quot; 
        
            alt=&quot;The formula for the sorting time.&quot;
        

        

        
        
        
            width=&quot;22&quot;
        
        
            height=&quot;5&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            The formula for the sorting time.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;Well, that is not quite correct. We forgot to consider the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Overhead_(computing)&quot;&gt;overhead&lt;&#x2F;a&gt;: When Mary
tries to pick up a sock, Stephen might reach for the same.
They both smile and one of them picks another sock.
In computing, a worker might do the same. Well, not smiling but picking another
task. When lots of workers share resources, these situations occur quite
frequently. And resolving the situation always takes a little extra time. So we are a
bit away from our optimal sorting speed because of that.&lt;&#x2F;p&gt;
&lt;p&gt;But it gets worse! Let’s say you have 100 workers for 100 socks.
In the beginning, every worker might take one sock and try to find a match for
it. Here’s the problem: As soon as they pick up one sock each, there are no
socks left. All workers are in a waiting state. The sorting takes forever.
That’s a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Deadlock&quot;&gt;deadlock&lt;&#x2F;a&gt;, and it’s one of the most frightening scenarios of parallel computing.&lt;&#x2F;p&gt;
&lt;p&gt;In this case, a simple solution is to put down the sock again and wait for some time until trying to get a new sock.
Another way out of the dilemma would be, to enforce some kind of “protocol” for sorting.
Think of a protocol as a silent agreement between the workers on how to achieve a common goal.&lt;&#x2F;p&gt;
&lt;p&gt;So, in our case, each worker might only be responsible for one color of socks.
Worker one takes the green socks, worker two the gray ones and so on.
With this simple trick, we can avoid a deadlock, because we work on completely
separate tasks.&lt;&#x2F;p&gt;
&lt;p&gt;But there’s still a catch. What if there are only four green socks and 4000 gray socks?
Worker one would get bored fairly quickly. He would sort the two pairs of socks in
no time and then watch worker two sort the rest.
That’s not really team spirit, is it?&lt;&#x2F;p&gt;
&lt;p&gt;Splitting up the work like this makes most sense, if we can assume that we
have around the same number of socks for every color.
This way we achieve roughly the same workload for
everyone.&lt;&#x2F;p&gt;
&lt;p&gt;The following histogram gives you an idea of what I mean:&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;the-essence-of-information&amp;#x2F;socks_even.svg&quot; 
        
            alt=&quot;Even piles of socks.&quot;
        

        

        
        
        
            width=&quot;160&quot;
        
        
            height=&quot;90&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            Even piles of socks.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In this case, we have about equally sized piles for each color. Looks
like a fair workload for every worker to me.&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;the-essence-of-information&amp;#x2F;socks_uneven.svg&quot; 
        
            alt=&quot;Uneven piles of socks.&quot;
        

        

        
        
        
            width=&quot;160&quot;
        
        
            height=&quot;90&quot;
         
    &#x2F;&gt;
    

    

    
        &lt;figcaption&gt;
            
            Uneven piles of socks.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;In the second case, we don’t have an equal distribution. I don’t want to sort the
gray socks in this example. We need to think a little harder here.&lt;&#x2F;p&gt;
&lt;p&gt;What can we do?&lt;&#x2F;p&gt;
&lt;p&gt;Most of the time it helps to think of other ways to split up work.
For example, we could have &lt;em&gt;two&lt;&#x2F;em&gt; workers sort the big gray pile together. One
sorts the large socks; the other one sorts the small ones. We run into another problem, though: Who decides what “large” and “small” means in this case?&lt;&#x2F;p&gt;
&lt;p&gt;So, instead of thinking too hard about a smarter approach, we decide to be
pragmatic here. Everyone just grabs an equally sized pile of socks — no
matter the color or the size — and gets
to work.&lt;&#x2F;p&gt;
&lt;p&gt;Most likely, there will be some remaining socks in each pile, which have no match.
That’s fine. We just throw them all together, mix the socks, create new piles from
that, and sort them again. We do so until we’re done.
We call that a &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Scheduling_(computing)#task_queue&quot;&gt;task queue&lt;&#x2F;a&gt;. It has two advantages: First, you don’t need any additional agreements between the workers and second, it scales reasonably
well with the number of workers without thinking too hard about the problem
domain.&lt;&#x2F;p&gt;
&lt;p&gt;The tricky part about distributed systems is, that seemingly straightforward solutions can fail
miserably in practice.&lt;&#x2F;p&gt;
&lt;p&gt;What if our small piles look like this?&lt;&#x2F;p&gt;
&lt;figure&gt;
    

    
    
    

    
        &lt;picture&gt;
            &lt;source srcset=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;the-essence-of-information&amp;#x2F;random_pile.avif&quot; type=&quot;image&#x2F;avif&quot; &#x2F;&gt;
    

    &lt;img src=&quot;https:&amp;#x2F;&amp;#x2F;endler.dev&amp;#x2F;2017&amp;#x2F;the-essence-of-information&amp;#x2F;random_pile.jpg&quot; 
        
            alt=&quot;A random pile of socks.&quot;
        

        

        
        
        
            width=&quot;590&quot;
        
        
            height=&quot;392&quot;
         
    &#x2F;&gt;
    
        &lt;&#x2F;picture&gt;
    

    

    
        &lt;figcaption&gt;
            
            A random pile of socks.
            
            
            
        &lt;&#x2F;figcaption&gt;
    
&lt;&#x2F;figure&gt;
&lt;p&gt;The number of pairs in each pile is… sobering.
What we could do is run a very quick presorting step to increase the number of matches. Or maybe you come up with an even better idea?&lt;br &#x2F;&gt;
The cool thing is, once you have found a faster approach, it works for similar tasks, too.&lt;&#x2F;p&gt;
&lt;p&gt;Problems like this have their roots in Computer Science, and they can be found everywhere.
Personally, I don’t like the term Computer Science too much. I prefer
the German term “Informatik”, which I would roughly translate as “Information Science”.
Because the real essence of what we’re doing here is to find a general way to solve a
whole &lt;em&gt;class&lt;&#x2F;em&gt; of problems. We think of the nature of objects and their properties.
We don’t sort socks; we try to answer the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=2Op3QLzMgSY&quot;&gt;fundamental questions of information&lt;&#x2F;a&gt;. Maybe now you can understand why I’m so passionate about this subject.&lt;&#x2F;p&gt;
&lt;p&gt;Oh, and here’s a related post about &lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2017&#x2F;why-i-love-programming&#x2F;&quot;&gt;why I love programming&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Why I Love Programming</title>
        <published>2017-03-15T00:00:00+00:00</published>
        <updated>2017-03-15T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2017/why-i-love-programming/"/>
        <id>https://endler.dev/2017/why-i-love-programming/</id>
        
        <summary type="html">&lt;p&gt;Programming has many faces. It is the science of structured thinking.
It is the art of eloquent expression.
It teaches you to be humble when you look at other peoples’ fascinating work.
Most of all, it teaches you a lot about yourself.&lt;br &#x2F;&gt;
While the syntax may change, the concepts will not.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Tools</title>
        <published>2011-10-30T00:00:00+00:00</published>
        <updated>2011-10-30T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2011/tools/"/>
        <id>https://endler.dev/2011/tools/</id>
        
        <content type="html" xml:base="https://endler.dev/2011/tools/">&lt;p&gt;For as long as I can think, religious flamewars have infected computer science.&lt;&#x2F;p&gt;
&lt;p&gt;Having arguments about technical topics can be healthy, but flamewars are not. I’m sick of it.
I’m fed up with people telling me that their work environment is oh-so better,
faster and so on. That’s fine, but it doesn’t matter. Your equipment only plays a supporting role. You don’t even need
a computer to do programming. Donald Knuth wrote algorithms on a
notepad. Alan Turing wrote the first chess computer on a piece of
paper. And it worked. Beat that!&lt;&#x2F;p&gt;
&lt;p&gt;For an average user, the next best system is probably good enough. Just a few bucks and you get an excellent piece of hardware which is completely sufficient to surf the web, chat, archive photos, write documents, listen to music and watch movies. You can do that with a Pentium IV, 256 MB RAM and any recent Operating System (you will likely get that one for free). Heck, you can use your old Commodore for most of that. Computers have been mature and reliable enough to do all that for ages. There’s no need to upgrade your system for Farmville, just like there’s no reason to buy a new car if the old one works perfectly fine. When it comes to software, many of us still use Office 2000 or Photoshop 8 or VisiCalc without feeling the urge to upgrade.&lt;&#x2F;p&gt;
&lt;p&gt;Professionals find themselves in a similar situation. Well, maybe we invest a bit more money, but still, our hardware is incredibly cheap compared to our salary (hopefully). Nothing is perfect, but most of the time &lt;em&gt;it’s good enough&lt;&#x2F;em&gt;. That compiler you were using a decade ago? Still does the job. We are still using slightly modified descendants of programming languages from computing stone-age. Even if you’re doing numerical computing for NASA, your primary work environment is a black box running a text editor or an IDE.&lt;&#x2F;p&gt;
&lt;p&gt;I don’t care what &lt;em&gt;you&lt;&#x2F;em&gt; are using to get things done. Find an environment that suits &lt;em&gt;your&lt;&#x2F;em&gt; needs and be happy with it. Maybe you use Emacs on a Lemote Yeelong netbook (hello Richard Stallman) or Vim on your workstation. It’s the same thing: A text editor running on a piece of metal.
You’re not a worse programmer for using Nano, ed or TextMate. Notepad works just fine, too. It loads files, saves files and lets you edit them in between. That’s a hell lot more functionality than Bill Gates and Paul Allen had when they wrote a BASIC interpreter for the Altair. If you find something you’re happy with, just stick with it but don’t start arguing. It isn’t worth your time.&lt;&#x2F;p&gt;
&lt;p&gt;Don’t feed the trolls. When it comes to software, don’t fall into the old FreeBSD vs. Linux vs. Windows vs. mum cliche. Instead, talk about your code. Let’s look at your problem-solving skills. Let’s be pragmatic here.&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Talk is cheap. Show me the code. - &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;lkml.org&#x2F;lkml&#x2F;2000&#x2F;8&#x2F;25&#x2F;132&quot;&gt;Linus Torvalds&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;I don’t care which programming language you are using. Java? Fine. Visual Basic? Great! Scala, Cobol, PHP, C++? All fine. Write in Assembler or lolcode. Don’t moan about the fact that language X is missing feature Y. Write a library or use something different. Stop saying JavaScript is a toy language. It just doesn’t fit your needs. Instead, show me your Lisp adventure game. Write an interpreter for Brainfuck. Do something. Move things.&lt;&#x2F;p&gt;
&lt;p&gt;Concerning PHP, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=2282523&quot;&gt;nir wrote on Hacker News&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Any idiot can write a snarky comment about PHP. Very few get to write code that has anywhere near the impact it had.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Will you fall off your chair when I admit that I &lt;em&gt;like&lt;&#x2F;em&gt; the PHP syntax?
OK, it has its rough edges (do we really need the $ sign?) but what’s
more important is how much I can get done with it. PHP was my long time
go-to language for off the hook, one time scripts. It looks a bit ugly
but it runs on any server and comes with an enormous amount of built-in
functionality. It’s great for rapid prototyping and gluing things together.
In fact, when you write a piece of software, what you should strive for is to produce &lt;em&gt;quite good&lt;&#x2F;em&gt; software and what you really need to accomplish is &lt;em&gt;good enough&lt;&#x2F;em&gt; software to make your users happy.&lt;&#x2F;p&gt;
&lt;p&gt;Zed A. Shaw puts it quite nicely in the afterword to &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;learnpythonthehardway.org&#x2F;&quot;&gt;Learn Python the hard way&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have been programming for a very long time. So long that it is incredibly boring to me. At the time that I wrote this book I knew about 20 programming languages and could learn new ones in about a day to a week depending on how weird they were. Eventually though this just became boring and couldn’t hold my interest. What I discovered after this journey of learning was that the languages didn’t matter, it was what you did with them. Actually, I always knew that, but I’d get distracted by the languages and forget it periodically. The programming language you learn and use does not matter. Do not get sucked into the religion surrounding programming languages as that will only blind you to their real purpose of being your tool for doing interesting things.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Don’t get emotional for any tool you use. An iPhone - I’m sorry to disappoint you - is just a phone. No magic. No “think different”. “But it’s evil!”, the ether says, “it’s not open source”. Well, Android just exists because Google needed to rapidly develop a mobile platform. It’s simply part of their business. There is no moral behind that. Google is a yet another company just like Microsoft or Apple.&lt;&#x2F;p&gt;
&lt;p&gt;My MacBook serves me as a solid tool, but if something “better” comes around, I will happily kick it out. I’ve ditched Firefox after five years just because Chrome is faster and I will get rid of Chrome when I find a worthy successor.
Vim is &lt;em&gt;quite good&lt;&#x2F;em&gt; in my opinion but if there’s a faster way to do things I’m not afraid to dump it. Instead get your hands dirty and fix the problems or craft something new.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Are you a Programmer?</title>
        <published>2011-10-20T00:00:00+00:00</published>
        <updated>2011-10-20T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2011/are-you-a-programmer/"/>
        <id>https://endler.dev/2011/are-you-a-programmer/</id>
        
        <content type="html" xml:base="https://endler.dev/2011/are-you-a-programmer/">&lt;p&gt;My geography teacher once told the story of her first lecture at University.
As an introduction, her professor asked the class to draw
a map of Germany without any help and as accurate as possible. To her surprise, she was not
able to fill the map with much detail. Even the shape of the country was a bit vague.&lt;&#x2F;p&gt;
&lt;p&gt;She had seen thousands of images of Germany (her mother country) but
wasn’t able to reproduce it from her blurry memory. She would have to look it up.&lt;&#x2F;p&gt;
&lt;p&gt;Doesn’t this sound familiar? We rely on machines to manage large portions
of our knowledge. There’s &lt;a href=&quot;https:&#x2F;&#x2F;endler.dev&#x2F;2011&#x2F;on-hard-work&#x2F;&quot;&gt;hard work&lt;&#x2F;a&gt; involved to learn something by heart.&lt;&#x2F;p&gt;
&lt;p&gt;Here is a similar test for programmers:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Using a programming language of your choice, write a correct sorting
algorithm with an average runtime complexity of O(n*log n) (Heapsort,
Quicksort, Bucketsort, you name it) on a piece of paper without the help of any
external tools.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And by &lt;em&gt;correct&lt;&#x2F;em&gt; I mean it must be free of bugs without any modifications when you type it in.&lt;&#x2F;p&gt;
&lt;p&gt;You would be surprised by the large percentage of professional software
engineers who &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.codinghorror.com&#x2F;why-cant-programmers-program&#x2F;&quot;&gt;can’t pull this off&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Some might argue that knowledge about details of programming language
syntax is unimportant: “Why learn all the little nitpicks when you know
how to use a search engine? Why start with a clean slate when you can easily
copy, paste and modify an example from a tutorial?
Every few years&#x2F;months I have to completely relearn the syntax for a different language anyway.”&lt;&#x2F;p&gt;
&lt;p&gt;But that is a myth. If you know only
one programming language &lt;strong&gt;really&lt;&#x2F;strong&gt; well - even if it is something
outdated like Fortran or COBOL - you could easily earn a fortune with
that knowledge. Suppose you started with C in 1975. You could still
use the same syntax today - almost four decades later.
Same for text editors. Emacs and Vim are both decades
old. They are battle-hardened. I don’t care which one you prefer, but you
will spend a large part of your life with your tools so invest the time to master them.&lt;&#x2F;p&gt;
&lt;p&gt;As a side note, it appears that very few people strive for perfection in anything they do.
They happily settle for “good enough”. This can have many different reasons, and I’m not
blaming anybody for not doing his homework but maybe I’m not alone with
that observation.&lt;&#x2F;p&gt;
&lt;p&gt;If you don’t know how to use your tools without a manual, you are a lousy craftsman.
If you need a dictionary to write a simple letter, you will have a hard
time becoming a writer because it would already be challenging for you to form elegant, fluent
sentences — let alone engaging and original stories.
I don’t want to read these books.&lt;&#x2F;p&gt;
&lt;p&gt;What makes a programmer?&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;She has at least one programming language she knows inside out.&lt;&#x2F;li&gt;
&lt;li&gt;She can implement standard algorithms (i.e. for sorting, searching)
and data-structures (i.e. trees, linked lists) which are robust and
reasonably fast on the fly.&lt;&#x2F;li&gt;
&lt;li&gt;She has at least a basic understanding of complexity theory and
programming concepts like recursion and pointers.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;But, to be a good programmer, you should&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Be able to code in at least two fundamentally different programming
paradigms (i.e. declarative, functional).&lt;&#x2F;li&gt;
&lt;li&gt;Have experience with big software architectures.&lt;&#x2F;li&gt;
&lt;li&gt;Be familiar with your programming environment like the operating system and a sophisticated text editor of your choice. Preferably one, that is
easily extendable.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And that is just the tip of the iceberg.
“There’s too much to learn!”, I hear some of you say.
Start slowly.
You need only three commands to start with Vim: &lt;code&gt;i&lt;&#x2F;code&gt;, &lt;code&gt;ESC&lt;&#x2F;code&gt;, &lt;code&gt;:wq&lt;&#x2F;code&gt;.
That’s enough for day one.&lt;&#x2F;p&gt;
&lt;p&gt;I realize that most of these essentials won’t be taught during lectures.
You have to learn a vast portion on your own.
But let’s face it: If you don’t know this stuff, you are &lt;em&gt;not&lt;&#x2F;em&gt; a programmer, you’re a freshman.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>On Hard Work</title>
        <published>2011-10-13T00:00:00+00:00</published>
        <updated>2020-03-12T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2011/on-hard-work/"/>
        <id>https://endler.dev/2011/on-hard-work/</id>
        
        <content type="html" xml:base="https://endler.dev/2011/on-hard-work/">&lt;p&gt;Great people get shaped by their achievements&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;There’s Thomas Edison who developed countless prototypes before selling a single light bulb.&lt;&#x2F;li&gt;
&lt;li&gt;The unemployed Joanne K. Rowling writing Harry Potter in a Cafe while caring for her child.&lt;&#x2F;li&gt;
&lt;li&gt;Steve Wozniak creating the first personal computer in his spare time while working at HP.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;What do they have in common?&lt;&#x2F;p&gt;
&lt;p&gt;They all lived through frustration and contempt but still reached their goals, even though the chances for success were
low. These people are stemming their strong will from an intrinsic curiosity.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dedication&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#dedication&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Dedication&lt;&#x2F;h2&gt;
&lt;p&gt;Sure, I love what I do. I want to be a programmer for the rest of my life, but sometimes it seems simply too hard to finish a project.
I get scared by the big picture and fear that I won’t finish on time. What I need is a different mindset.&lt;&#x2F;p&gt;
&lt;p&gt;Dhanji R. Prasanna, a former Google Wave team member &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20150717074857&#x2F;https:&#x2F;&#x2F;rethrick.com&#x2F;p&#x2F;mmm&#x2F;&quot;&gt;made this observation&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;And this is the essential broader point–as a programmer you must have a series of wins, every single day. It is the Deus Ex Machina of hacker success. It is what makes you eager for the next feature, and the next after that.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;While Google Wave has not been commercially successful, it sure was a
technical breakthrough — and it was a drag to push it out into public.
We always have to see our goal right in front of us, as we take a billion baby steps to reach it.
This is true for any profession. Winners never give up.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;direction&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#direction&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Direction&lt;&#x2F;h2&gt;
&lt;p&gt;Today it is easier to accomplish something meaningful than ever before.&lt;&#x2F;p&gt;
&lt;p&gt;If you are reading this, you have access to a powerful instrument — a
computer with an Internet connection. We live in a time where a single
person can accomplish miracles without hard physical labor.
A time where billions of people can grow a business from their desk, get famous in minutes,
publish books in seconds and have instant access to large amounts of
data. The most potent development over the last 100
years has been the reduction of communication costs. Transferring a bit of
information to the other end of the world is virtually free and takes
fractions of a second. While proper education was a privilege of a lucky few
well into the 20th century, learning new things is now mostly a question of
will.&lt;&#x2F;p&gt;
&lt;p&gt;Nevertheless, learning is still a tedious task,
requiring patience and determination.
As the amount of information has increased, so have the ways of distraction.
Losing focus is just a click away.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;devotion&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#devotion&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Devotion&lt;&#x2F;h2&gt;
&lt;p&gt;Everybody can start something. Few will finish anything.
That’s because getting things done is hard, even if you love what
you’re doing. (Watch the beginnings of &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.de&#x2F;gp&#x2F;product&#x2F;B08QDFDRVY?ie=UTF8&amp;amp;tag=matthiasendle-21&amp;amp;camp=1638&amp;amp;linkCode=xm2&amp;amp;creativeASIN=B08QDFDRVY&quot;&gt;&lt;em&gt;There Will Be Blood&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.amazon.de&#x2F;gp&#x2F;product&#x2F;B08D5H2QTY&#x2F;ref=as_li_tl?ie=UTF8&amp;amp;tag=matthiasendle-21&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;linkCode=as2&amp;amp;creativeASIN=B08D5H2QTY&amp;amp;linkId=5dc5fa7545b60138290abe114d7c527ehttps:&#x2F;&#x2F;www.amazon.de&#x2F;gp&#x2F;product&#x2F;B08D5H2QTY&#x2F;ref=as_li_tl?ie=UTF8&amp;amp;tag=matthiasendle-21&amp;amp;camp=1638&amp;amp;creative=6742&amp;amp;linkCode=as2&amp;amp;creativeASIN=B08D5H2QTY&amp;amp;linkId=5dc5fa7545b60138290abe114d7c527e&quot;&gt;&lt;em&gt;Primer&lt;&#x2F;em&gt;&lt;&#x2F;a&gt; for a
definition of &lt;em&gt;hard work&lt;&#x2F;em&gt;.)&lt;&#x2F;p&gt;
&lt;p&gt;No matter what they tell you, achieving anything sustainable means hustling. It means making
sacrifices. It means pushing through.
It means selling something even though it isn’t perfect. Your beautiful project might turn into an ugly groundhog in
the end. Put makeup on it and get it out the door.&lt;&#x2F;p&gt;
&lt;p&gt;On a report about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.bluesnews.com&#x2F;abrash&#x2F;chap70.shtml&quot;&gt;Quake’s 3D-Engine&lt;&#x2F;a&gt;, developer Michael Abrash says:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;By the end of a project, the design is carved in stone, and most of the work involves fixing bugs, or trying to figure out how to shoehorn in yet another feature that was never planned for in the original design. All that is a lot less fun than starting a project, and often very hard work–but it has to be done before the project can ship. As a former manager of mine liked to say, “After you finish the first 90% of a project, you have to finish the other 90%.” It’s that second 90% that’s the key to success.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;A lot of programmers get to that second 90%, get tired and bored and frustrated, and change jobs, or lose focus, or find excuses to procrastinate. There are a million ways not to finish a project, but there’s only one way to finish: Put your head down and grind it out until it’s done. Do that, and I promise you the programming world will be yours.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;That last part has influenced me a lot.
The dedication, the urgency to reach your aims must come from within you.
It’s your raw inner voice speaking — don’t let it fade away.
And when you are close to giving up, stop thinking so hard. Just try to
push forward and make a tiny step in the right direction.
Ship it!&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Overkill – Java as a First Programming Language</title>
        <published>2010-02-12T00:00:00+00:00</published>
        <updated>2020-03-17T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2010/overkill-java-as-a-first-programming-language/"/>
        <id>https://endler.dev/2010/overkill-java-as-a-first-programming-language/</id>
        
        <content type="html" xml:base="https://endler.dev/2010/overkill-java-as-a-first-programming-language/">&lt;p&gt;I recently talked to a student in my neighborhood about his first programming
experiences. They started learning &lt;em&gt;Java&lt;&#x2F;em&gt; at school, and it soon turned out to
be horrible.&lt;&#x2F;p&gt;
&lt;p&gt;A lot of us learned to code in languages like &lt;em&gt;BASIC&lt;&#x2F;em&gt; or &lt;em&gt;Pascal&lt;&#x2F;em&gt;. There was no
object orientation, no sophisticated file I&#x2F;O and almost no modularization…
and it was great. In &lt;em&gt;BASIC&lt;&#x2F;em&gt; you could just write&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-constant&quot;&gt;PRINT&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;HELLO WORLD&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;and you were done. This was actually a running program solving a basic and
reoccurring problem: Output some text on a screen.&lt;&#x2F;p&gt;
&lt;p&gt;If you wanted to do the same thing in &lt;em&gt;Java&lt;&#x2F;em&gt; you just write:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; Main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;  public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-primitive z-storage z-type z-primitive z-java&quot;&gt; void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-object z-array z-java&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;    System&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;println&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello, world!&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;  }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Do you see how much knowledge about programming you must have to achieve the
easiest task one could think of? Describing the program to a novice programmer
may sound like this:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Create a Main class containing a main-method returning void expecting a string
array as a single argument using the &lt;code&gt;println&lt;&#x2F;code&gt; method of the &lt;code&gt;out&lt;&#x2F;code&gt; object of
class &lt;code&gt;PrintStream&lt;&#x2F;code&gt; passing your text as a single argument.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;— please just don’t forget your brackets. This way your first programming
hours are guaranteed to be great fun.&lt;&#x2F;p&gt;
&lt;p&gt;OK. So what are the alternatives? I admit that nobody wants to write &lt;em&gt;BASIC&lt;&#x2F;em&gt;
anymore because of its lack of a sophisticated standard library for graphics
(&lt;em&gt;Java&lt;&#x2F;em&gt; doesn’t have one either) and its weak scalability. The language has to
be clean and straightforward. It should be fast enough for numerical tasks but
not as wordy as the rigid C-type bracket languages (sorry C++ guys). It should
have a smooth learning curve and provide direct feedback (compiled languages
often suck at that point). It should encourage clean code and reward best
practices. One language that provides all that is &lt;em&gt;&lt;em&gt;Python&lt;&#x2F;em&gt;&lt;&#x2F;em&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;And &lt;em&gt;Python&lt;&#x2F;em&gt; has even more: hundreds of libraries that help you with almost
everything, good integration into common IDEs (PyDev in Eclipse, IDLE…), a
precise and elegant syntax.&lt;&#x2F;p&gt;
&lt;p&gt;Here is our program from above written in &lt;em&gt;Python&lt;&#x2F;em&gt;:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;print&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;Hello World&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There’s no need to know about object orientation, scopes and function arguments
at this point. No householding or book-keeping. Yes, it’s an interpreted
language, but that’s not a deal breaker for beginners.&lt;&#x2F;p&gt;
&lt;p&gt;If you aren’t convinced yet, printing and formatting text output in &lt;em&gt;Java&lt;&#x2F;em&gt; is
relatively easy for an advanced programmer but the gruesome stuff begins with
file input:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;java&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt; java&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-storage z-modifier z-import z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-storage z-modifier z-import z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt;BufferedReader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt; java&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-storage z-modifier z-import z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-storage z-modifier z-import z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt;FileNotFoundException&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt; java&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-storage z-modifier z-import z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-storage z-modifier z-import z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt;FileReader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword&quot;&gt;import&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt; java&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-storage z-modifier z-import z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt;io&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-storage z-modifier z-import z-java&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier z-import z-java&quot;&gt;IOException&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; class&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-type&quot;&gt; fileIO&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt;    public&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-storage z-modifier&quot;&gt; static&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-primitive z-storage z-type z-primitive z-java&quot;&gt; void&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; main&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-object z-array z-java&quot;&gt;String&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;]&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; args&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt;        String&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; filename&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;test.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;,&lt;&#x2F;span&gt;&lt;span&gt; line&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;        try&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt;            BufferedReader&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; myFile&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;                new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; BufferedReader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;new&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt; FileReader&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;filename&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt;            while&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span&gt; line &lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt;=&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; myFile&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;readLine&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; !=&lt;&#x2F;span&gt;&lt;span class=&quot;z-constant z-language&quot;&gt; null&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;                System&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt;out&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;println&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;line&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;            }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt;FileNotFoundException&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;printStackTrace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-keyword z-control&quot;&gt; catch&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; (&lt;&#x2F;span&gt;&lt;span class=&quot;z-storage z-type z-storage z-type z-java&quot;&gt;IOException&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable&quot;&gt; e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable&quot;&gt;            e&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span class=&quot;z-entity z-name z-function&quot;&gt;printStackTrace&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-punctuation&quot;&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I hear you say: “Dude, file I&#x2F;O is pretty complex. It’s just the way it is”.
That’s true… &lt;em&gt;internally&lt;&#x2F;em&gt; . But a beginner should get an easy interface.
&lt;em&gt;Python&lt;&#x2F;em&gt; shows how it’s done:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo z-code&quot;&gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-variable z-variable z-legacy z-builtin z-python&quot;&gt;file&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-support z-function&quot;&gt; open&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-string&quot;&gt;test.txt&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation z-string&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-keyword z-operator&quot;&gt; =&lt;&#x2F;span&gt;&lt;span class=&quot;z-variable z-variable z-legacy z-builtin z-python&quot;&gt; file&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;.&lt;&#x2F;span&gt;&lt;span&gt;read&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span class=&quot;z-support z-function&quot;&gt;print&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;(&lt;&#x2F;span&gt;&lt;span&gt;text&lt;&#x2F;span&gt;&lt;span class=&quot;z-punctuation&quot;&gt;)&lt;&#x2F;span&gt;&lt;span class=&quot;z-invalid&quot;&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The code goes hand in hand with the natural understanding of how the process
works: “The computer opens a file, reads it and prints it”. Even a five-year-old
kid can understand that. Nobody would start to explain: “Before you can read a
file you need a BufferedReader that works on a FileReader…” even if this is
precisely how it works &lt;em&gt;internally&lt;&#x2F;em&gt;. You want to explain the big picture at
first. The elementary principles of teaching a computer how to do useful stuff.
Otherwise, you will start frustrating beginners and fool them into thinking that
they are not bright enough for programming. Programming is fun and starting with
it is the most crucial step. So don’t spoil that experience with layers of
unneeded abstraction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;links&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#links&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Links&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Response to this article (almost ten years later): &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;dev.to&#x2F;dzh&#x2F;why-kotlin-may-be-better-than-java-and-python-as-the-first-programming-language-37d5&quot;&gt;Why Kotlin may be better than Java and Python as the first programming language&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Howto Sort a Vector or a List in C++ using STL</title>
        <published>2010-01-27T00:00:00+00:00</published>
        <updated>2010-01-27T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2010/howto-sort-a-vector-or-a-list-in-c-using-stl/"/>
        <id>https://endler.dev/2010/howto-sort-a-vector-or-a-list-in-c-using-stl/</id>
        
        <summary type="html">&lt;p&gt;A little code snippet that people need very often.&lt;&#x2F;p&gt;</summary>
        
    </entry>
    <entry xml:lang="en">
        <title>Why I Love Text Files</title>
        <published>2010-01-10T00:00:00+00:00</published>
        <updated>2010-01-10T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2010/why-i-love-text-files/"/>
        <id>https://endler.dev/2010/why-i-love-text-files/</id>
        
        <content type="html" xml:base="https://endler.dev/2010/why-i-love-text-files/">&lt;p&gt;Text files are the single most important way we can communicate with computers. It’s no coincidence that they are also the most vital way to interact with other human beings. What we can achieve with text files is invaluable: Write it once and refer to it whenever you want to get the message across in the future. Write a program (it’s just text), save it and let the machine execute it whenever you like. Write another text file which contains the rules for the execution of your program and the computer runs your application exactly as you specified (&lt;code&gt;cron&lt;&#x2F;code&gt; files do that on Unix).&lt;&#x2F;p&gt;
&lt;p&gt;Text files can be structured in any way you can imagine. Some flavours are &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.json.org&#x2F;&quot;&gt;JSON&lt;&#x2F;a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;daringfireball.net&#x2F;projects&#x2F;markdown&#x2F;&quot;&gt;Markdown&lt;&#x2F;a&gt; and &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.w3.org&#x2F;Graphics&#x2F;SVG&#x2F;&quot;&gt;SVG&lt;&#x2F;a&gt;. It’s all just text. There exist a billion of programs and algorithms to access, modify and distribute text files. You can write them with &lt;em&gt;Emacs&lt;&#x2F;em&gt;, print them on a terminal, pipe them through &lt;em&gt;sed&lt;&#x2F;em&gt; and send them via email to a friend who publishes them on the web. Because text files are so important we have good support for them on any computing system. On Unix, everything is a file and &lt;em&gt;HTML&lt;&#x2F;em&gt; is just structured text. It’s a simple and powerful tool to make a contribution to society that outlasts our lives.&lt;&#x2F;p&gt;
&lt;p&gt;I have a single text file in my mac dock bar which is called &lt;code&gt;TODO.txt&lt;&#x2F;code&gt;. I open it every day, and after years of experimenting with different task management apps from simple command line tools to sophisticated online information storage systems, I always come back to plain text files. And the explanation is simple: If humanity will still be around a thousand years from now, chances are that plain text files are one of the very few file formats that will still be readable.&lt;&#x2F;p&gt;
&lt;p&gt;Text files are an incremental part of how we can modify our environment without even leaving our desk. They have no overhead and can contain a single thought or the complete knowledge of our species. Distributing textual information is so vital for us that we permanently develop faster distribution networks – the fastest by now being the internet.&lt;&#x2F;p&gt;
&lt;p&gt;On the web, you have instant access to a virtually endless amount of information and data distributed as plain text files. New web services made accessing the data even easier, offering &lt;code&gt;APIs&lt;&#x2F;code&gt; and &lt;code&gt;feeds&lt;&#x2F;code&gt;. You can pull down the data from their servers and make statistics with a programming language of your choice. As you may have noticed, my affinity to text files partially comes from my programming background. As &lt;a rel=&quot;external&quot; href=&quot;http:&#x2F;&#x2F;matt.might.net&#x2F;articles&#x2F;console-hacks-exploiting-frequency&#x2F;&quot;&gt;Matt Might&lt;&#x2F;a&gt; correctly points out on his blog:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;The continued dominance of the command line among experts is a testament to the power of linguistic abstraction: when it comes to computing, a word is worth a thousand pictures.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;Whenever you like a text on the web, just link to it and create a wonderful chain of ideas. Want to read it later or recommend it to a friend? Just share the text or print it on paper. The fact that we all take such things for granted is a testament for the power of text files and their importance for the &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Information_Age&quot;&gt;information age&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Running Legacy Code</title>
        <published>2009-11-08T00:00:00+00:00</published>
        <updated>2009-11-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              matthias@endler.dev (Matthias Endler)
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://endler.dev/2009/running-legacy-code/"/>
        <id>https://endler.dev/2009/running-legacy-code/</id>
        
        <content type="html" xml:base="https://endler.dev/2009/running-legacy-code/">&lt;p&gt;This short article deals with a severe problem in software development: bit rot.
When switching to a new platform (for instance from Windows XP to Windows Vista&#x2F;7), the programmers need to make sure that old bits of code run flawlessly. There are several ways to achieve this goal that will be discussed in the next paragraphs:&lt;&#x2F;p&gt;
&lt;h2 id=&quot;porting-the-code&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#porting-the-code&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Porting the code&lt;&#x2F;h2&gt;
&lt;p&gt;This is generally considered a hard path to follow. For non-trivial legacy code-blocks, chances are high that they contain side-effects and hacks to make them work in different environments. Porting code means replacing parts of the program that use functions and methods that don’t exist anymore with new ones which make use of the modern libraries  and routines of the new platform. The significant advantages are maintainable software and sometimes faster running programs. But it may be needed to hack the new platform libraries in order to preserve the whole functionality of an old application. When changing an algorithm inside legacy code, the ported version may become unstable. Thus there may be better ways of maintaining obsolete code today.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;emulators&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#emulators&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Emulators&lt;&#x2F;h2&gt;
&lt;p&gt;Emulators work much the same like porting the code. You replace old function calls with new ones to make everything work again. &lt;br &#x2F;&gt;However you don’t alter the old codebase itself (because you may not have the source code available) but you create a new compatibility layer that “translates” the communication between the underlying operating system and software (our new platform) and our old software. Emulation can also be very fast and run stable for many years but writing an emulator can be even harder than porting the code because an educational guess may be needed to figure out how the program works internally. Additionally, the emulator itself may become obsolete in the future and might eventually  be replaced by a new one.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;virtual-machines&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#virtual-machines&quot;&gt;
    &lt;svg height=&quot;22&quot; viewbox=&quot;0 0 24 24&quot; width=&quot;22&quot; xmlns=&quot;http:&#x2F;&#x2F;www.w3.org&#x2F;2000&#x2F;svg&quot;&gt;
        &lt;path d=&quot;M0 0h24v24H0z&quot; fill=&quot;none&quot;&gt;&lt;&#x2F;path&gt;
        &lt;path d=&quot;M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7c-2.76.0-5 2.24-5 5s2.24 5 5 5h4v-1.9H7c-1.71.0-3.1-1.39-3.1-3.1zM8 13h8v-2H8v2zm9-6h-4v1.9h4c1.71.0 3.1 1.39 3.1 3.1s-1.39 3.1-3.1 3.1h-4V17h4c2.76.0 5-2.24 5-5s-2.24-5-5-5z&quot;&gt;&lt;&#x2F;path&gt;
    &lt;&#x2F;svg&gt;
&lt;&#x2F;a&gt;Virtual machines&lt;&#x2F;h2&gt;
&lt;p&gt;During the last years, a new approach was gaining popularity. The idea is simple: Don’t touch anything. Take the whole platform and copy it in order to run old software. The old software runs on top of the old operating system within a virtual machine that runs on the new platform.&lt;&#x2F;p&gt;
&lt;p&gt;From a sane software developers view, this method is ridiculous. A lot of resources are wasted along the way. The system is busier switching contexts from an old platform to the new one and back than running the actual legacy program. However, with cheap and capable hardware everywhere this idea gets more and more interesting. As &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;blog.codinghorror.com&#x2F;hardware-is-cheap-programmers-are-expensive&#x2F;&quot;&gt;Steve Atwood coined it&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;
&lt;blockquote&gt;
&lt;p&gt;Always try to spend your way out of a performance problem first by throwing faster hardware at it.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;
&lt;p&gt;And he’s right. The Microsoft developers did the same on their new NT 6.0 platform (Vista, Windows 7, Windows Server 2008…): Windows XP is running on a virtual machine. This way everything behaves just like one would run the software on the old system. And by optimizing the performance bottlenecks (input&#x2F;output, context switches), one gets a fast and stable, easy to maintain product.&lt;&#x2F;p&gt;
&lt;p&gt;Every method has its major advantages and disadvantages. It’s on the developer to select the appropriate strategy.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
