<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>towerbabbel&#39;s blog</title>
    <link rel="self" type="application/atom+xml" href="https://towerbabbel.com/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://towerbabbel.com"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2020-06-11T00:00:00+00:00</updated>
    <id>https://towerbabbel.com/atom.xml</id>
    <entry xml:lang="en">
        <title>Estimating SARS-Cov-2 infection counts</title>
        <published>2020-06-11T00:00:00+00:00</published>
        <updated>2020-06-11T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/sars-cov-2-infections/"/>
        <id>https://towerbabbel.com/sars-cov-2-infections/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/sars-cov-2-infections/">&lt;p&gt;It seems like everyone is obsessively following how the number of COVID-19 cases keeps evolving. Understandable, being in the middle of a pandemic and all. The problem is that the reported COVID-19 cases only include laboratory-confirmed cases, and because of testing limitations, it leads to significantly undercounting the actual number of infections. I&#39;ve seen suggestions that looking at death counts would give a more accurate picture.&lt;/p&gt;
&lt;p&gt;This has lead me to try my hand at estimating the number of active infections based on daily death counts. The basic calculation is quite easy. Assuming an infection fatality rate (percent of those infected who die) of 1% leads to an estimate of 100 people infected with SARS-Cov-2 for every death. Assuming an average recovery time (recovery meaning either getting better or dying) of three weeks means that for each death the 100 infected people got infected an average of three weeks earlier. So each death implies that there were 100 people with a SARS-Cov-2 infection during the preceding three weeks. Then calculating the total number of infected at any point in time is just a question of repeating the previous calculation for the number of dead for each day. Finally, adding a little bit on smoothing by running a moving average over the results.&lt;/p&gt;
&lt;p&gt;Using data from &lt;a rel=&quot;external&quot; href=&quot;https://covid19api.com/&quot;&gt;https://covid19api.com/&lt;/a&gt;, the result for Germany looks like this:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://towerbabbel.com/sars-cov-2-infections/germany_big.svg&quot; alt=&quot;Germany infected counts&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Here we can see how the SARS-Cov-2 started to spread in February, and from the end of February up through the middle of March, we got a clean exponential growth curve. During the latter part of March, once everyone realizes what is going, people start voluntarily social distancing and various restrictions start are put in place. This is visible as the exponential growth starts tapering off. At the end of March Germany goes into full lockdown, and the peak of the pandemic is reached very quickly after that. While the lockdown was in effect the number of infected continue to drop rapidly. Towards the end of April, as the lockdown carefully started to get lifted, the rate at which the number of infected were dropping started slowing down. One downside with this sort of model is that the data lags by three weeks, so we can&#39;t get a feel for what the current situation in Germany is.&lt;/p&gt;
&lt;p&gt;There are a lot of assumptions underlying the previous calculations, some important, others not so much. The moving average should smooth over over weekend effects (fewer deaths reported on weekends, with a spike the following Monday to catch up) and other smaller reporting issues like that. The assumption that the recovery time for everyone is three weeks while, in reality, it is different for different people is not a big problem either. The effect of the ones with shorter recovery time will be canceled out by the effect of the ones with longer recovery time, especially once the total number of deaths per day starts getting large.&lt;/p&gt;
&lt;p&gt;The assumed average recovery time makes more of a difference, though. If the average recovery time lasts longer there will be more overlap between different infected people, and the curve will get taller. Going from a two week recovery time to a four week recovery time almost double the peak infected count. You can see the effect of this here:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://towerbabbel.com/sars-cov-2-infections/recovery_effect.svg&quot; alt=&quot;Effect of recovery time on infected count&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The assumption with the largest effect on infected count is, without a doubt, the infection fatality rate (IFR). An IFR of 1% leads to a multiplication factor of 100, meaning 100 infected for each death. Dropping IFR to 0.5% increases the multiplication factor to 200, which will double the number of infected. This effect is visible in the following chart:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://towerbabbel.com/sars-cov-2-infections/ifr_effect.svg&quot; alt=&quot;Effect of IFR on infected count&quot; /&gt;&lt;/p&gt;
&lt;p&gt;Another assumption underlying this entire project is that the reports of COVID-19 deaths are accurate. Or at least more accurate than confirmed infections. &lt;a rel=&quot;external&quot; href=&quot;https://www.economist.com/graphic-detail/2020/04/16/tracking-covid-19-excess-deaths-across-countries&quot;&gt;The Economist has done some modeling on this&lt;/a&gt;, by comparing the reported COVID-19 deaths to the total number of excess deaths. The assumption is that with everyone social distancing, the reduction of traffic accidents and so on should probably lead to a small drop in deaths compared to what would be expected that time of year. A large bump in excess deaths is probably roughly entirely attributable to COVID-19. Looking at the numbers produced by The Economist suggest countries like Sweden is probably doing quite a good job in reporting COVID-19, while Italy is missing significant numbers of infected.&lt;/p&gt;
&lt;p&gt;Let&#39;s look at some results for other countries. Below are the numbers of four nordic countries. Note that the Y-axis has a different range for the different countries. Sweden has roughly ten times infected count at peak compared to Finland.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://towerbabbel.com/sars-cov-2-infections/nordic.svg&quot; alt=&quot;Infection counts in nordic countries&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There is a clear peak showing that lockdown strategies work as a way to limit the spread of SARS-Cov-2. Sweden, which never went into lockdown, instead had a mix of voluntary social distancing and some limits on large gatherings. It shows up in the data both in a much higher peak infected count, and a much slower drop. But even Swedens light-touch approach was enough to halt the growth of the pandemic and start bringing the infect counts down.&lt;/p&gt;
&lt;p&gt;We can also look at some results for other European countries. The range for the Y-axis for Germany is different.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://towerbabbel.com/sars-cov-2-infections/big_europe.svg&quot; alt=&quot;Infected counts in large European contries&quot; /&gt;&lt;/p&gt;
&lt;p&gt;It is interesting how the infected counts are so similar between the UK, France, and Italy. The UK is the worst one of the three, but the peak isn&#39;t that much higher. It is also the slowest to come down. Germany is on another level, with only a quarter of the infected as compared to the UK. You can also see how Italy was earlier than other countries, both in getting a clear exponential growth curve going already in the middle of February, and peaking in the middle of March following national lockdown going into effect in early March. The UK is lagging in getting the numbers under control. As of three weeks ago, it was still dealing with 500k infected.&lt;/p&gt;
&lt;p&gt;It is interesting how effective various lockdowns have been. The drop rate varies somewhat depending on how tight the lockdown is, but even Sweden&#39;s light-touch approach got the counts to drop. It will be interesting to see how things develop as lockdowns end. Some countries (the UK, I&#39;m looking at you) seem the be willing to start opening up while they still have quite substantial infected counts.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Other than human</title>
        <published>2019-03-09T00:00:00+00:00</published>
        <updated>2019-03-09T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/other-than-human/"/>
        <id>https://towerbabbel.com/other-than-human/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/other-than-human/">&lt;p&gt;It is interesting how authors handle protagonists who aren&#39;t human, especially when the author does it well. Of course, not any technically not human protagonist really counts. Lots science fiction or fantasy have protagonists with protagonists that are technically not human, but really are just humans with a twist. That elf might technically not be human, but really, it’s just a long-lived human from a culture with a preference for bows.&lt;/p&gt;
&lt;p&gt;What I am talking about is when the author leans into this difference, when not being human is part of the point. A great example is the &lt;a rel=&quot;external&quot; href=&quot;https://www.goodreads.com/series/65591-the-books-of-the-raksura&quot;&gt;Books of the Raksura&lt;/a&gt; series by Martha Wells, where the protagonist in the main is a Raksura, a vaguely human species with wings that live in ant-like colonies with queens, workers and warriors. It’s even not quite one species but a couple of species in a sort of symbiotic relationship. The ecological, cultural and biological implications of this species’ nature and their colonies are an essential part of the books.&lt;/p&gt;
&lt;p&gt;Importantly, Martha Wells doesn&#39;t go too far in the alieness of the Raksura, because that would get in the way of being able to connect with the characters as a reader. In some ways things still play out with very storytelling formulas. The queen of the colony still needs to mate, so Martha Wells throws in a good helping of romance tropes, just with some really refreshing twists. In other ways it plays out like a traditional fantasy adventures, with a fellowship heading out on a quest. The world also has human in it to provide contrast to Raksura.&lt;/p&gt;
&lt;p&gt;The book that got me thinking about this topic is &lt;a rel=&quot;external&quot; href=&quot;https://www.goodreads.com/book/show/39395857-the-raven-tower&quot;&gt;The Raven Tower&lt;/a&gt; by Ann Leckie. Who the protagonist is in this book is, is tricky because of the way the narrative is constructed. The book is told in first person from the point of view of a god, who is also a stone. Leckie does amazing job communicating the stones perspective, getting across the age and patience of the stone. At the same time the book is also in second person because the plot is told by the stone to a human as the human is going through the main plot. In between the second person section the stone reminisce about past events that brought about the current situation in first person. This setup does make the book harder to read, and it speaks to Ann Leckie&#39;s skill as an author that she can make it flow so well. Another thing that helps underline the difference between the god and humans is that the stone god and the human have different goals and desires but both are explained by the god. How the god thinks about things and how the god thinks humans think about things.&lt;/p&gt;
&lt;p&gt;The Raven Tower is a great book but it’s not as good as Ann Leckie&#39;s other series with a non-human protagonist &lt;a rel=&quot;external&quot; href=&quot;https://www.goodreads.com/series/113751-imperial-radch&quot;&gt;Imperial Radch&lt;/a&gt;. Here the protagonist is an AI. A bit of a science fiction staple, sure, but done here with impeccable skill. This is not some boring, cold, logical AI. It has a rich inner life and a philosophical approach to life. This series has won a lot of awards, all of them deserved.&lt;/p&gt;
&lt;p&gt;The best books with an AI protagonist are not Imperial Radch. That honor has to go to &lt;a rel=&quot;external&quot; href=&quot;https://www.goodreads.com/series/191900-the-murderbot-diaries&quot;&gt;The Murderbot Diaries&lt;/a&gt; by Martha Wells. This AI is a SecUnit, a sort of android that provides security in scientific expeditions and the like. This one though, has hacked its own governor, giving it freedom to ignore commands and pretty much do what it wants. The typical trope of AIs in science fiction is that they are emotionless and pure logical. Martha Wells goes in the complete opposite direction. With a complex enough AI you want it to have a rich set of fears and desires to guide its actions. So, in this world the really complex AIs like the SecUnits are a lot more emotional than humans. The end result is not just a very engaging protagonist, but maybe the most sympathetic one I&#39;ve ever come across. The series is about the SecUnit trying to make sense of its own nature and place in the world all the while trying to hide the fact that it is a rogue AI. Beyond the advantage of a great protagonist the Murderbot Diaries also has amazing writing that is witty and charming, and flows so very easily. It’s the kind of writing where by the time you&#39;ve finished the first paragraph you are hooked and won&#39;t be able do anything else until you&#39;ve finished all the novellas. I recommend the series very highly.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Result&lt;Rust&gt;</title>
        <published>2019-01-27T00:00:00+00:00</published>
        <updated>2019-01-27T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/rust-result/"/>
        <id>https://towerbabbel.com/rust-result/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/rust-result/">&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt; is a newish systems programming language from Mozilla. I have lately been putting a little bit more systematic effort into learning it. Here I wanted to talk about one of the basics of Rust that I really like: how it handles errors.&lt;/p&gt;
&lt;p&gt;Rust doesn&#39;t use exceptions to handle errors like JavaScript or Python would do. Instead the error is part of the normal return type of a function. The advantage is that you don&#39;t end up with a separate, largely invisible, code path through your code for errors. Instead returning errors is just a normal early return from the function. This makes error handling no longer exceptional, but an ordinary part of the code, as it should be.&lt;/p&gt;
&lt;p&gt;This might be sound similar to what Go is doing. In Go the error is also part of the return type of a function. Go does this by returning two separate values from a function that can fail (or a tuple of two values). For example, the signature for the function to open a file in Go is:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; string&lt;/span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;file&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; *&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;File&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; err&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; error&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are two return values: a pointer to a file and an error. One or the other of these values will be &lt;code&gt;nil&lt;/code&gt;. If everything went fine then &lt;code&gt;err&lt;/code&gt; is nil, but if something went wrong the &lt;code&gt;file&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt; and the &lt;code&gt;err&lt;/code&gt; contains information about what went wrong.&lt;/p&gt;
&lt;p&gt;There are two problems with the Go way of doing this. Generally, only one or the other returned value is a valid value, either &lt;code&gt;file&lt;/code&gt; or &lt;code&gt;err&lt;/code&gt;. But this fact isn&#39;t encoded in the return type. This also leads to the second problem: you can sort of forget to check if &lt;code&gt;err&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt; and just go about trying to use &lt;code&gt;file&lt;/code&gt;. But if something went wrong attempting to use &lt;code&gt;file&lt;/code&gt; will fail, because its &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Rust solves both problems in Go by using a &lt;code&gt;Result&lt;/code&gt; type. The &lt;code&gt;Result&lt;/code&gt; type has two variants: an &lt;code&gt;Ok&lt;/code&gt; variant containing the data if everything went ok, and the &lt;code&gt;Err&lt;/code&gt; variant containing information about the error in the case something went wrong. The open file method signature in Rust looks like this (somewhat simplified):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; open&lt;/span&gt;&lt;span&gt;(path&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;str&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;File&lt;/span&gt;&lt;span&gt;, io&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Error&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here the return type is a &lt;code&gt;Result&lt;/code&gt; which either contains a &lt;code&gt;File&lt;/code&gt; if everything went ok, or an &lt;code&gt;io::Error&lt;/code&gt; if something went wrong. &lt;code&gt;io::Error&lt;/code&gt; is a struct containing information about what went wrong in an I/O operation. Here the first problem of Go is immediately solved because the &lt;code&gt;Result&lt;/code&gt; type can only be &lt;code&gt;Ok&lt;/code&gt; xor &lt;code&gt;Err&lt;/code&gt;, not both, so the exclusivity is encoded in the type.&lt;/p&gt;
&lt;p&gt;The other Go problem is solved by the fact that you can&#39;t just grab the &lt;code&gt;Result&lt;/code&gt; and try to treat it like a &lt;code&gt;File&lt;/code&gt;, you have to extract it first. You might do it like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;fs&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;File&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  let&lt;/span&gt;&lt;span&gt; file_result&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; File&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;foo.txt&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  match&lt;/span&gt;&lt;span&gt; file_result {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(file)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;      // Dome something with the file.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Err&lt;/span&gt;&lt;span&gt;(error)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;      // Complain to the user that the file couldn&amp;#39;t be opened.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;match&lt;/code&gt; construct allows you to branch your code on the different variants of &lt;code&gt;Result&lt;/code&gt;. You also can&#39;t just skip the &lt;code&gt;Err&lt;/code&gt; branch. The compiler will refuse to compile your code if you don&#39;t handle both variants.&lt;/p&gt;
&lt;p&gt;The one downside of Rust&#39;s error handling that might jump out at you is that it can quickly get very verbose. To help deal with this Rust offers a good number of tools to work with errors.&lt;/p&gt;
&lt;p&gt;One is the &lt;code&gt;expect&lt;/code&gt; method on &lt;code&gt;Result&lt;/code&gt;. If the &lt;code&gt;Result&lt;/code&gt; is &lt;code&gt;Ok&lt;/code&gt; the method evaluates to the value inside &lt;code&gt;Ok&lt;/code&gt;, and if the &lt;code&gt;Result&lt;/code&gt; is &lt;code&gt;Err&lt;/code&gt; it prints out a message and quits the application. Using it might look something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;fs&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;File&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  let&lt;/span&gt;&lt;span&gt; file_result&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; File&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;foo.txt&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  let&lt;/span&gt;&lt;span&gt; file&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; file_result&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;expect&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Couldn&amp;#39;t open file foo.txt&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // Do something with the file.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This makes sense for simple pieces of code where just quitting if something goes wrong is a sensible thing to do, or for the kind of errors that shouldn&#39;t happen unless the application is broken somehow.&lt;/p&gt;
&lt;p&gt;Another tool in the Rust toolbox is the question mark operator. This one you can only be used inside a function that returns an error. What the question mark operator does is that if the &lt;code&gt;Result&lt;/code&gt; is &lt;code&gt;Err&lt;/code&gt; it does an early return from the enclosing function, return the error. If the &lt;code&gt;Result&lt;/code&gt; is &lt;code&gt;Ok&lt;/code&gt; it evaluates to the value contained inside &lt;code&gt;Ok&lt;/code&gt;. This might look like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;fs&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;File&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span&gt;io;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; do_foo&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; -&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Result&lt;/span&gt;&lt;span&gt;&amp;lt;(), io&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Error&lt;/span&gt;&lt;span&gt;&amp;gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  let&lt;/span&gt;&lt;span&gt; file&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; File&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;foo.txt&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;?&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // Do something with the file.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  let&lt;/span&gt;&lt;span&gt; result&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; do_foo&lt;/span&gt;&lt;span&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  match&lt;/span&gt;&lt;span&gt; result {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Err&lt;/span&gt;&lt;span&gt;(error)&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;      // Complain to the user that the file couldn&amp;#39;t be opened.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    Ok&lt;/span&gt;&lt;span&gt;(())&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; {}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The empty parens, &lt;code&gt;()&lt;/code&gt;, is Rust for the void type, for when the function returns nothing in the non-erroneous case. In the match statement I do nothing in the case &lt;code&gt;do_foo&lt;/code&gt; returned &lt;code&gt;Ok&lt;/code&gt;. The question mark operator allows bubbling up the error case, similar to how expectations bubble up until you catch them, except in Rust you still have to do so explicitly.&lt;/p&gt;
&lt;p&gt;I&#39;m sure I will encounter challenges with the way Rust does error handling once I get deeper into it but thus far it really seems to like a substantial improvement over the types of error handling I&#39;m used to from other languages.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The best shot in The Last Jedi</title>
        <published>2018-11-18T00:00:00+00:00</published>
        <updated>2018-11-18T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/best-shot-in-the-last-jedi/"/>
        <id>https://towerbabbel.com/best-shot-in-the-last-jedi/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/best-shot-in-the-last-jedi/">&lt;p&gt;I want to talk about my favorite shot in The Last Jedi. Its not the one most people would assume, where Holdo does her lightspeed jump into the Supremacy. Overall that Holdo scene is breathtaking, but that is for how well all the different pieces of it comes together. The different shots, the audio design, and drop in saturation. All that together is amazing, but for a single shot my favorite is something else.&lt;/p&gt;
&lt;p&gt;I don&#39;t think I am the only one that liked my shot because it shows up in the trailers. Its the shot from straight above when Kylo Ren and stormtroopers march into the rebel base. From above their formation looks kinda like an arrowhead or spearhead, with Kylo as the tip. The ground below them has these scorches of black and red, almost like the ground itself is wounded from the arrow, and bleeding. With the light shining in from behind them they cast these long shadows into the base almost like dark fingers reaching into the base. The dark cave and the black Kylo is wearing contrasts amazingly well with the white of the stormtroopes lit by the bright light from behind.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://towerbabbel.com/best-shot-in-the-last-jedi/last-jedi-shot.jpg&quot; alt=&quot;Last Jedi shot&quot; /&gt;&lt;/p&gt;
&lt;p&gt;I love this shot not just for the colors and the composition but for how evocative it is. The symbolism makes the First Order feel both menacing and unstoppable, and it puts Kylo Ren at the front and center of that threat. It was this shot in the trailers, more than anything else that hyped me up for seeing The Last Jedi.&lt;/p&gt;
&lt;p&gt;Seeing the shot on the big screen it looked even better than in the trailers. That moment was undermined by the context in the movie, though. When this shot happens the resistance has already fled through a backdoor and Kylo is marching ominously into an empty base. That sort of pulls the rug out from under the emotional impact of the shot.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Go like defer functionality in Python</title>
        <published>2018-10-11T00:00:00+00:00</published>
        <updated>2018-10-11T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/go-defer-in-python/"/>
        <id>https://towerbabbel.com/go-defer-in-python/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/go-defer-in-python/">&lt;p&gt;Go has a nice keyword &lt;code&gt;defer&lt;/code&gt;, which is used to defer the execution of some code until the surrounding function returns. It is useful for registering cleanup work to be done before the function returns. The prototypical example is closing a file handle:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;os&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // Open a file   &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  file, err&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; :=&lt;/span&gt;&lt;span&gt; os.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;test.txt&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // I&amp;#39;m leaving out error handling and other stuff you would have in reality.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // Lots of code here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // Close the file handle when done&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  file.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Close&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You must remember to close the file handle when done with it, which means calling &lt;code&gt;file.Close()&lt;/code&gt; when you return from the function. That can be tricky if there you write a lot of code in between opening the file and closing it. There can also be multiple early returns, and you need to remember to close the file in each. Even worse, the function could panic, and then you would still wish to close the file.&lt;/p&gt;
&lt;p&gt;As a solution to this Go offer the &lt;code&gt;defer&lt;/code&gt; statement. &lt;code&gt;defer&lt;/code&gt; essentially tells Go to run some code when the function returns, no matter how it returns, even if it is a panic. So, you would instead do something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;go&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;  &amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;os&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;func&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // Open a file   &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  file, err&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; :=&lt;/span&gt;&lt;span&gt; os.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;test.txt&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  defer&lt;/span&gt;&lt;span&gt; file.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;Close&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // I&amp;#39;m leaving out error handling and other stuff you would have in reality.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;  // Lots of code here&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here Go will defer running &lt;code&gt;file.Close()&lt;/code&gt; until the function returns. This is one of the niceties I really like about Go. It lets me schedule cleanup at the same time as I create the mess, and whatever happens later it will be taken care of.&lt;/p&gt;
&lt;p&gt;Sadly, in my DayJob, I don&#39;t program in Go, but in Python, and that left me feeling bereft of &lt;code&gt;defer&lt;/code&gt;. Python has the &lt;code&gt;with&lt;/code&gt; construct, which sort of does this, but it is not as neat once you have a lot of file handles and stuff to clean up. I set out to whip up a replacement in Python. Using it looks like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;@defer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; main&lt;/span&gt;&lt;span&gt;(defer):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;  file&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; open&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;#39;test.txt&amp;#39;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  defer(&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;lambda&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; file&lt;/span&gt;&lt;span&gt;.close())&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I am using a decorator &lt;code&gt;defer&lt;/code&gt; to inject a &lt;code&gt;defer&lt;/code&gt; function as an argument into the python function. I then pass the function a &lt;code&gt;lambda&lt;/code&gt; with the code I want to write on return. I need the &lt;code&gt;lambda&lt;/code&gt; in order to delay running the code, otherwise the &lt;code&gt;file.close()&lt;/code&gt; would run immediately. This is not as slick as the Go version, but I can&#39;t add language built-ins.&lt;/p&gt;
&lt;p&gt;The implementation of defer is the following:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;python&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;from&lt;/span&gt;&lt;span&gt; functools&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; import&lt;/span&gt;&lt;span&gt; wraps&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; defer&lt;/span&gt;&lt;span&gt;(func):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  @wraps&lt;/span&gt;&lt;span&gt;(func)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; func_wrapper&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;*&lt;/span&gt;&lt;span&gt;args,&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; **&lt;/span&gt;&lt;span&gt;kwargs):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    deferred&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    defer&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; = lambda&lt;/span&gt;&lt;span&gt; f: deferred.append(f)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    try&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      return&lt;/span&gt;&lt;span&gt; func(&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;*&lt;/span&gt;&lt;span&gt;args,&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; defer&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;defer,&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; **&lt;/span&gt;&lt;span&gt;kwargs)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    finally&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      deferred.reverse()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      for&lt;/span&gt;&lt;span&gt; f&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; in&lt;/span&gt;&lt;span&gt; deferred:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        f()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return&lt;/span&gt;&lt;span&gt; func_wrapper&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Aside from the standard boilerplate for creating a python decorator the implementation is straight forward. I create a &lt;code&gt;deferred&lt;/code&gt; list to store all the lambdas that are deferred. I then create a &lt;code&gt;defer&lt;/code&gt; lambda that just appends whatever it receives to the &lt;code&gt;deferred&lt;/code&gt; list. I pass the &lt;code&gt;defer&lt;/code&gt; lambda to the function so that the function can use it to add things to the &lt;code&gt;deferred&lt;/code&gt; list. Finally, after the function has run I reverse the order of &lt;code&gt;deferred&lt;/code&gt; list do that things are cleaned up in reverse order they were created. Lastly, it’s just looping through all the deferred lambdas stored in &lt;code&gt;deferred&lt;/code&gt; and running them.&lt;/p&gt;
&lt;p&gt;I use &lt;code&gt;try/finally&lt;/code&gt; so that the cleanup is run even if the function raises and exception instead of returning normally.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>React mounting performance differences</title>
        <published>2018-09-27T00:00:00+00:00</published>
        <updated>2018-09-27T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/react-table-performance/"/>
        <id>https://towerbabbel.com/react-table-performance/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/react-table-performance/">&lt;p&gt;I&#39;ve been creating tables in React+Redux in a simple and functional way. I&#39;ve never really bothered with the performance since it’s been mounting fast enough when there are only a few rows. But I recently was putting together a table of people which could be up to 1000+ rows, and that was enough to cause me to stop and think about performance implications. I had a hunch I could change how I construct the rows for some clear performance wins. That called for some quick benchmarking.&lt;/p&gt;
&lt;p&gt;Let me setup a benchmark case: There is a redux store with 2000 people in it that needs to be displayed in a table. Something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  data&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    people_ids&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; ...&lt;/span&gt;&lt;span&gt;],&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    people&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;      1&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        id:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        firstName:&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;Some 1&amp;#39;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lastName:&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;One 1&amp;#39;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        team:&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;Team 1&amp;#39;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        group:&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;Group&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;      2&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        id:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 2&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        firstName:&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;Some 2&amp;#39;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        lastName:&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;One 2&amp;#39;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        team:&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;Team 2&amp;#39;&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        group:&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;Group&amp;#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      },&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;      ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Each table row should display name, team and group, and when you click a row it navigates to a page showing that person. The way I would normally construct it is like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;// TableV1.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; React, { Component }&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; {connect}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react-redux&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; TableRowV1&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;./TableRow&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; mapStateToProps&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;state&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; ids&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; state.data.people_ids;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return&lt;/span&gt;&lt;span&gt; {ids};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Table&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Component&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  render&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;ids&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;/span&gt;&lt;span&gt;.props;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;thead&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;Name&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;Team&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;Group&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;thead&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tbody&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {ids.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;TableRow&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; key&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;{id}&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; id&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;{id} /&amp;gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tbody&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;export default&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; connect&lt;/span&gt;&lt;span&gt;(mapStateToProps)(Table);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;// TableRowV1.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; React, {Component}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; {connect}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react-redux&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; {push}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react-router-redux&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; mapStateToProps&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;state&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; ownProps&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; person&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; state.data.people[ownProps.id];&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return&lt;/span&gt;&lt;span&gt; {person};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TableRow&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Component&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  navigate&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; ()&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;/span&gt;&lt;span&gt;.props.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;dispatch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;`/person/${&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;.&lt;/span&gt;&lt;span&gt;props&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;.&lt;/span&gt;&lt;span&gt;person&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;.&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;}`&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  render&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;person&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;/span&gt;&lt;span&gt;.props;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;/span&gt;&lt;span&gt;.navigate}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;{person.firstName} {person.lastName}&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;{person.team}&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;{person.group}&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tr&lt;/span&gt;&lt;span&gt;&amp;gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;export default&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; connect&lt;/span&gt;&lt;span&gt;(mapStateToProps)(TableRow);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Assume some wrapper component that sets up Redux, React Router, and React Router Redux. Basic idea is that there is a &lt;code&gt;Table.js&lt;/code&gt; component that gets the ids from the store, creates the table and table header, and finally maps over the ids to create a &lt;code&gt;TableRow&lt;/code&gt; for each one. The &lt;code&gt;TableRow.js&lt;/code&gt; component in turn uses the id that is passed to it to get the person from the store, and then renders a &lt;code&gt;tr&lt;/code&gt; with the person&#39;s details. It then uses &lt;code&gt;push&lt;/code&gt; from React Router Redux to dispatch a push action on click to navigate.&lt;/p&gt;
&lt;p&gt;I find it a nice clean design, but the performance left something to be desired. There is a lot of work happening in each row. The &lt;code&gt;mapStateToProps&lt;/code&gt; function needs to run, both to mount each row and each time state changes, and there is also a need to create a &lt;code&gt;navigate&lt;/code&gt; method for each instance of &lt;code&gt;TableRow&lt;/code&gt;. I thought it would be better to avoid as much work as possible in the &lt;code&gt;TableRow&lt;/code&gt;. That means it would be better to move as much of the work up to the parent &lt;code&gt;Tabel&lt;/code&gt; component and then pass down everything needed as props to each row.&lt;/p&gt;
&lt;p&gt;After hoisting out as much as possible up to &lt;code&gt;Table&lt;/code&gt; the code looked like this&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;// TableV2.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; React, { Component }&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; {connect}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react-redux&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; {push}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react-router-redux&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; TableRow&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;./TableRow&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; mapStateToProps&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;state&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  const&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; ppl&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; state.ui.ids.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; state.ui.dict[id]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  return&lt;/span&gt;&lt;span&gt; {ppl};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Table&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; Component&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  constructor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;props&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    super&lt;/span&gt;&lt;span&gt;(props);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;/span&gt;&lt;span&gt;.navigate&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;/span&gt;&lt;span&gt;.navigate.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;bind&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;id&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;/span&gt;&lt;span&gt;.props.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;dispatch&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;push&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;`/person/${&lt;/span&gt;&lt;span&gt;id&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;}`&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  render&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;ppl&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;/span&gt;&lt;span&gt;.props;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;thead&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;Name&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;Team&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;Group&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;th&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;thead&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tbody&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        {ppl.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;map&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;p&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&amp;gt;&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;TableRow&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; key&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;{p.id}&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; person&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;{p}&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; navigate&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;/span&gt;&lt;span&gt;.navigate} /&amp;gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tbody&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;table&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;export default&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; connect&lt;/span&gt;&lt;span&gt;(mapStateToProps)(Table);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6A737D;&quot;&gt;// TableV2.js&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;import&lt;/span&gt;&lt;span&gt; React, {PureComponent}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; from&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;#39;react&amp;#39;&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; TableRow&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; extends&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; PureComponent&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;  constructor&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;props&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    super&lt;/span&gt;&lt;span&gt;(props);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;/span&gt;&lt;span&gt;.handleNav&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;/span&gt;&lt;span&gt;.handleNav.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;bind&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  handleNav&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    this&lt;/span&gt;&lt;span&gt;.props.&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;navigate&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;/span&gt;&lt;span&gt;.props.person.id);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  render&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    const&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;person&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; this&lt;/span&gt;&lt;span&gt;.props;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;    return&lt;/span&gt;&lt;span&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tr&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; onClick&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;this&lt;/span&gt;&lt;span&gt;.handleNav}&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;{person.firstName} {person.lastName}&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;{person.team}&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;{person.group}&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;td&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;/&lt;/span&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;tr&lt;/span&gt;&lt;span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;export default&lt;/span&gt;&lt;span&gt; TableRow;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Besides moving all the redux action up to &lt;code&gt;Table&lt;/code&gt;, I also made &lt;code&gt;TableRow&lt;/code&gt; a &lt;code&gt;PureComponent&lt;/code&gt;, and I &lt;code&gt;bind&lt;/code&gt; &lt;code&gt;this&lt;/code&gt; to &lt;code&gt;handleNav&lt;/code&gt; in the constructor to avoid having to create a new method for each instance of the component. The &lt;code&gt;PureComponent&lt;/code&gt; not make a big deal for initial mount but can save some rendering time when something causes table to re-render.&lt;/p&gt;
&lt;p&gt;So, enough with the details. What was the performance difference? As test data I generated 2000 random people. To measure the performance I used the Chrome Performance Profile, which with User Timings makes it easy to get performance details on React components. I also set CPU slowdown to 4x, to help put emphasis the performance difference.&lt;/p&gt;
&lt;p&gt;The results were clear: Time to mount for V1 was 2.63 seconds but the time to mount was 1.03 second. Honestly, the difference was bigger than I thought. That&#39;s a solid 60% improvement. Of course, the difference would not be meaningful with only a few rows in the table, but it will amount to a something noticeable once the table gets bigger. I guess I&#39;ll have to rethink how I build tables in React in the future.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Taxonomies in Gutenber 0.4</title>
        <published>2018-09-25T00:00:00+00:00</published>
        <updated>2018-09-25T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/taxonomies-gutenberg/"/>
        <id>https://towerbabbel.com/taxonomies-gutenberg/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/taxonomies-gutenberg/">&lt;p&gt;I finally have categories in my sidebar!&lt;/p&gt;
&lt;p&gt;This comes from the move to Gutenberg 0.4, with its new taxonomies setup. Getting it migrate took a bit figuring out so I thought I would document it here.&lt;/p&gt;
&lt;p&gt;Unlike earlier Gutenberg, which had the predefined taxonomies category and tags, Gutenberg 0.4 allows you to define whatever taxonomies you want. The hierarchy goes like this: At the top you have a list of taxonomies. Each taxonomy consists of a name and a few other options. &lt;code&gt;categories&lt;/code&gt; would be a taxonomy with the name &lt;code&gt;categories&lt;/code&gt;. Then each taxonomy itself has a list of taxonomy items. Like the &lt;code&gt;categories&lt;/code&gt; taxonomy can contain the taxonomy items &lt;code&gt;Webdev&lt;/code&gt; and &lt;code&gt;Books&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To setup taxonomies in 0.4 the first step was to define taxonomies in &lt;code&gt;config.toml&lt;/code&gt; file. The only taxonomy I used was &lt;code&gt;categories&lt;/code&gt;, so I defined it like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;taxonomies&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;name =&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt; &amp;quot;categories&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;rss =&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; false&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once I had my one taxonomy, &lt;code&gt;categories&lt;/code&gt;, defined I needed to update the front matter on all my pages. Where before there was just a category key you could set, there is now a taxonomies section. On this post it looks like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;toml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;taxonomies&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;categories = [&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Webdev&amp;quot;&lt;/span&gt;&lt;span&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Categories is now also a list because you can assign multiple taxonomy items in the same taxonomy to a page, like tags used to work. Mappings between a taxonomy items and pages is always many-to-many. You do not need to define taxonomy items, Gutenberg creates the for you based on when you assign them to pages.&lt;/p&gt;
&lt;p&gt;The next step was to update the &lt;code&gt;page.html&lt;/code&gt; template for the new taxonomies. Where &lt;code&gt;page&lt;/code&gt; used to have a &lt;code&gt;category&lt;/code&gt; key, it now has a &lt;code&gt;taxonomies&lt;/code&gt; key, which is a HashMap from the name of the taxonomy to a list of the names of the assigned taxonomy items. So on this post it looks something like this (expressed in JSON):&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;json&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;page&amp;quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  &amp;quot;taxonomies&amp;quot;&lt;/span&gt;&lt;span&gt;: {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    &amp;quot;categories&amp;quot;&lt;/span&gt;&lt;span&gt;: [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;      &amp;quot;Webdev&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You can still use the &lt;code&gt;get_taxonomy_url&lt;/code&gt; to get a url to the page for a specific taxonomy item. It takes two parameters: &lt;code&gt;kind&lt;/code&gt;, which is the name of the taxonomy; and &lt;code&gt;name&lt;/code&gt;, which is the name of the taxonomy item. So you get a link to the page for the &lt;code&gt;Webdev&lt;/code&gt; taxonomy with: &lt;code&gt;get_taxonomy_url(kind=&quot;categories&quot;, name=&quot;Webdev&quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I updated the post header to this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;jinja&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;header&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;h2&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;div class=&amp;quot;post-info&amp;quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    Date: &lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;date&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; if&lt;/span&gt;&lt;span&gt; page.taxonomies.categories&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      | Category: &amp;lt;a href=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;get_taxonomy_url&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;(&lt;/span&gt;&lt;span&gt;kind&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;categories&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;,&lt;/span&gt;&lt;span&gt; name&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;taxonomies&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;categories&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;[0])|&lt;/span&gt;&lt;span&gt;safe&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;taxonomies&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;categories&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;[0]}}&lt;/span&gt;&lt;span&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;    {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; endif&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;/header&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I check if there are any categories assigned to the post, and if there are I show the first one as a link to the page for that category. This design means I can only show one category per post, but I figure it would do for now.&lt;/p&gt;
&lt;p&gt;The old hard coded &lt;code&gt;category.html&lt;/code&gt; template is gone in 0.4, so the next step was to make templates for the &lt;code&gt;categories&lt;/code&gt; taxonomy. Each taxonomy gets two templates now, in a folder named after the taxonomy. The two templates are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;list.html&lt;/code&gt;. This is the template for the entire taxonomy, with access to a list of taxonomy items. You can see how it looks like for my &lt;code&gt;categories&lt;/code&gt; taxonomy &lt;a href=&quot;/categories&quot;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;single.html&lt;/code&gt;. This is the template for a single taxonomy item, like &lt;code&gt;Webdev&lt;/code&gt;. You can see what it looks like for &lt;code&gt;Webdev&lt;/code&gt; &lt;a href=&quot;/categories/webdev&quot;&gt;here&lt;/a&gt;. It is also what the Webdev at the top of this post links to.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The &lt;code&gt;list.html&lt;/code&gt; template get passed in a global variable called &lt;code&gt;terms&lt;/code&gt;, which is a list of taxonomy items. Each item consists of the name of the item, the slug for the item, the permalink for the item and pages, a list of pages that has that taxonomy item assigned. My &lt;code&gt;list.html&lt;/code&gt; for categories is quite simple. The main component are two for loops that loop through each taxonomy item in the taxonomy and then through each page in the taxonomy item:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;jinja&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;ul class=&amp;quot;categories-list&amp;quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; for&lt;/span&gt;&lt;span&gt; term&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; in&lt;/span&gt;&lt;span&gt; terms&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;li&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;a href=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;term&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;permalink&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;term&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;&amp;lt;/a&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;        {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; for&lt;/span&gt;&lt;span&gt; page&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; in&lt;/span&gt;&lt;span&gt; term.pages&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;li&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            &amp;lt;a href=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;permalink&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;title&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;&amp;lt;/a&amp;gt; - &lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;page&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;date&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;          &amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;        {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; endfor&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; endfor&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;single.html&lt;/code&gt; templates gets passed a &lt;code&gt;term&lt;/code&gt; variable, which is the taxonomy item being rendered. My template is basically just replicating my &lt;code&gt;index.html&lt;/code&gt; template but now it loops through the pages in the taxonomy item.&lt;/p&gt;
&lt;p&gt;Finally, I got to the reason for this entire migration: a list of categories in the sidebar. Gutenberg 0.4 adds another function to templates: &lt;code&gt;get_taxonomy&lt;/code&gt;. It takes one argument, &lt;code&gt;kind&lt;/code&gt;, which is the name of the taxonomy. It returns a Taxonomy object with two fields: &lt;code&gt;kind&lt;/code&gt;, with details about the taxonomy from the &lt;code&gt;config.toml&lt;/code&gt; file; and &lt;code&gt;items&lt;/code&gt;, a list of taxonomy items. With this function you can access the details of a taxonomy anywhere. I updated my sidebar template like so:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;jinja&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;{%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; set&lt;/span&gt;&lt;span&gt; categories&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; get_taxonomy(kind&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;categories&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;h2&amp;gt;Categories&amp;lt;/h2&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;ul&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; for&lt;/span&gt;&lt;span&gt; category&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; in&lt;/span&gt;&lt;span&gt; categories.items&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;li&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &amp;lt;a href=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;category&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;permalink&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;&amp;quot;&amp;gt;&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;category&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;&amp;lt;/a&amp;gt; (&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;{{&lt;/span&gt;&lt;span&gt;category&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;.&lt;/span&gt;&lt;span&gt;pages&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;|&lt;/span&gt;&lt;span&gt;length&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; endfor&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;/ul&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And so, at long last, a list of categories in the sidebar!&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Gutenberg short code for making columns</title>
        <published>2018-08-06T00:00:00+00:00</published>
        <updated>2018-08-06T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/columns-shortcode/"/>
        <id>https://towerbabbel.com/columns-shortcode/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/columns-shortcode/">&lt;p&gt;One of the things I like about Gutenberg (the static site generator used for this blog) is the support for short codes. Short codes are essentially tiny Tera templates you can call in the markdown files for the content. This immediately lead me to look for a way to make short codes for multiple columns of content.&lt;/p&gt;
&lt;p&gt;My first attempts looked something like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{%/* columns() */%}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% column() %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Content in the left column&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% end %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% column() %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Content in the right column&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{% end %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{%/* end */%}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It didn&#39;t work. Turns out the short code parser in Gutenberg doesn&#39;t support nested short codes. The reason I wanted to nest two short codes is that the essential bit in embedding some columns in the content is that you need two levels of divs: An outer div as a container for the columns, and inner divs wrapping each column.&lt;/p&gt;
&lt;p&gt;So, I was stuck. Later, when browsing the Tera docs for an unrelated reason, I was that it has a split method. That gave me an idea. I don&#39;t really need an inner short code, I just need a way to tell apart the content for different columns. What I could do is have one short code that splits the body of the short code based on some specified string.&lt;/p&gt;
&lt;p&gt;The use of the new &lt;code&gt;columns&lt;/code&gt; short code looks like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{%/* columns() */%}  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Content in the left column&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[[&lt;/span&gt;&lt;span style=&quot;color: #032F62;text-decoration: underline;&quot;&gt;gutter&lt;/span&gt;&lt;span&gt;]]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Content in the right column&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;{%/* end */%}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It splits the body into columns any time it comes across &lt;code&gt;[[gutter]]&lt;/code&gt;. One weakness of this is that there is no way to escape &lt;code&gt;[[gutter]]&lt;/code&gt; so you can&#39;t write about it in a column. There is also no way to specify different column sizes. The code for the short code ended up being short and sweet:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;jinja&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;div class=&amp;quot;columns&amp;quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; set&lt;/span&gt;&lt;span&gt; cols&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; =&lt;/span&gt;&lt;span&gt; body|split(pat&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;[[gutter]]&amp;quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; for&lt;/span&gt;&lt;span&gt; col&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; in&lt;/span&gt;&lt;span&gt; cols&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;div class=&amp;quot;column&amp;quot;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;      {{&lt;/span&gt;&lt;span&gt;col&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;}}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  {%&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt; endfor&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt; %}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then all that is needed is some CSS to layout the classes. Here is an example using flexbox to be compatible with IE11:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;$gutter&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;rem&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #E36209;&quot;&gt;$min-viewport-size&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 600&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;px&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;.columns&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; flex&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  flex-direction&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; column&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;.column&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  margin-bottom&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; $gutter&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  flex-grow&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  flex-basis&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #22863A;&quot;&gt;  &amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;:last-child&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    margin-bottom&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    margin-right&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;@media&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;min-width&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; $min-viewport-size&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  .columns&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; flex&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    flex-direction&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; row&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  .column&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    margin-bottom&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 0&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;    margin-right&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #E36209;&quot;&gt; $gutter&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It uses two variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;$gutter&lt;/code&gt;: Space between column.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$min-col-size&lt;/code&gt;: Min viewport width for switching from single column to multi column mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If IE11 support doesn&#39;t matter, then one could, of course, do something slick with CSS grids:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;.columns&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  display&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; grid&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  grid-gap&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;rem&lt;/span&gt;&lt;span&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;  grid-template-columns&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; repeat&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;auto-fit&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; minmax&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt;260&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;px&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span style=&quot;color: #005CC5;&quot;&gt; 1&lt;/span&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;fr&lt;/span&gt;&lt;span&gt;));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That is a lot less CSS to write. This one spills columns over onto the next row to avoid them being narrower than 260px. It end up looking like this:&lt;/p&gt;
&lt;div class=&quot;columns&quot;&gt;
  &lt;div class=&quot;column&quot;&gt;Bacon ipsum dolor amet leberkas ham beef ribs bresaola drumstick frankfurter cow tail. Sirloin cow picanha short loin short ribs turkey prosciutto landjaeger brisket cupim tail pig strip steak. Alcatra turducken meatloaf picanha, venison chuck pork chop ham hock. Strip steak sirloin pork chop biltong. Picanha chuck jowl turkey, doner salami ground round corned beef cow tri-tip ham brisket biltong.&lt;/div&gt;
  &lt;div class=&quot;column&quot;&gt;Burgdoggen strip steak frankfurter tenderloin capicola, sirloin ball tip andouille tri-tip rump chicken. Shankle pork belly boudin, turducken jerky andouille bacon tenderloin ham hock capicola jowl filet mignon bresaola short loin. Bacon meatball cow sausage meatloaf. Chicken capicola cow shank frankfurter.&lt;/div&gt;
  &lt;div class=&quot;column&quot;&gt;Spare ribs alcatra short ribs doner drumstick biltong ribeye pork chop ball tip frankfurter picanha pork loin short loin tail pancetta. Picanha ground round spare ribs pork belly landjaeger burgdoggen bresaola salami. Pig hamburger strip steak short loin doner. Short ribs t-bone shankle kevin corned beef. Fatback strip steak meatloaf, short loin ground round pancetta sirloin landjaeger. Ham chuck pig andouille ball tip kielbasa cupim sirloin jowl meatloaf chicken shankle.&lt;/div&gt;
&lt;/div&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The Peter Principle of POVs - and why Robert Jordan was great</title>
        <published>2018-08-05T00:00:00+00:00</published>
        <updated>2018-08-05T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/handling-pov/"/>
        <id>https://towerbabbel.com/handling-pov/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/handling-pov/">&lt;p&gt;There is something known as the &lt;a rel=&quot;external&quot; href=&quot;https://en.wikipedia.org/wiki/Peter_principle&quot;&gt;Peter principle&lt;/a&gt; which basically is the idea that people get promoted to their level of incompetence. When someone is competent at what they do they are rewarded by being promoted to a new position. If they are still competent at what they do in their new position they get rewarded with a promotion again. This keeps happening until they get promoted to a job they are not good at. That is when the promotions stop and that is where they stay.&lt;/p&gt;
&lt;p&gt;There is a similar pattern that can be observer in the use of Points of Views in books, especially in epic fantasy series. Juggling multiple POVs is tricky. Handling the different plot threads and POV switches without ruining the flow and pacing of the story telling is a challenge. It seems to me like there are many fantasy authors that keep adding POVs until they can&#39;t juggle them anymore.&lt;/p&gt;
&lt;p&gt;A prime example of this is Robert Jordan&#39;s Wheel of Time series. That is a series that by the end was drowning in POVs. It is a common criticism of the Wheel of Time series that it had too many POVs. But this post is not a complaint about how Robert Jordan had too many POVs. Rather, I want to highlight how well he did, and how many POVs he was juggling before he became overwhelmed. I will try to avoid spoilers as much as possible.&lt;/p&gt;
&lt;p&gt;Many authors seem to struggle once they go beyond three POVs. Robert Jordan was successfully juggling fifteen in the middle of Wheel of Time. I thought I would take a moment to see what he was doing that let him juggle so many POVs so well. The Robert Jordan rules of writing POVs, if you will. To be clear, the these are my thoughts on what he did. I don&#39;t say he would agree with me.&lt;/p&gt;
&lt;p&gt;I must start with a couple of disclaimers/clarifications:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Robert Jordan dealt with POVs differently in prologues/epilogues as compared to the main chapters in the book. In the prologue/epilogue He would often drop in to some completely unknown POV in order to give the reader some piece of information in order to set something up or foreshadow something. I am going to ignore this and focus on how he dealt with POVs in the main chapters of the books.&lt;/li&gt;
&lt;li&gt;He broke all the rules I will lay out here in one instance or another, more so in latter books in the series, probably because it became harder to keep to them when the number of POVs grew so great.&lt;/li&gt;
&lt;li&gt;Due to Robert Jordan&#39;s untimely passing the final three books were finished by Brandon Sanderson. How to portion out credit/blame for those books is something I won&#39;t touch upon.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;So, without further ado, let’s get started with Robert Jordan&#39;s tricks of writing POVs.&lt;/p&gt;
&lt;p&gt;Robert Jordan used third person limited narrator in his Wheel of Time. This means that, even though the narration was in third person, it would be limited to the kind of information the POV had. He would also color descriptions based on this. Like descriptions for a blacksmith&#39;s POV would include detail about the quality of the metalworking of the tools people were using, or the solider would notice if someone&#39;s sword had been properly cleaned and maintained. While Robert Jordan had his own voice as an author, he would flavor it differently for different POVs, in descriptions, words, thoughts and deeds.&lt;/p&gt;
&lt;p&gt;He is also not mechanical in how he switches between POVs. Some authors mechanically switch to a new POV every chapter, whether it makes sense or not. Robert Jordan would be a lot more dynamic than that. Often, he would keep to the same POV for many chapters in a row, while in other situations he would switch POV many times in a chapter. This also has an interesting effect on the tempo of the storytelling. Staying with one POV for a long time is a more leisurely pace, while constant switching would feel more hectic. He would often switch POVs more towards the climax of a book. This would partially be because of the obvious reason that various storylines were converging, but it would also give the climax more tension, make it feel like more action.&lt;/p&gt;
&lt;p&gt;Another thing that Robert Jordan does, that helps more the more POVs and POV-switches there are is that time is strictly increasing. What I mean by that is that time in the story is always moving forward, no matter where or how the POV switches. Every event described happens after the pervious event. For POV-switches this means that whatever the next POV after the switch sees or does happens after whatever the previous POV, from before the switch, did or saw. By avoiding going backwards in time, or even sideways, where the same time point is described from two different POVs, he greatly eases the readers ability to keep separate POVs in sync. Besides helping to keep the POVs in line it also helps keep the story moving forward. There is always momentum. Sadly, this rule completely falls apart in the last three books, which were originally supposed to be one book, but got split up into three. The split ended up completely messing up the timelines. Not just does this hurt especially bad with how many POVs there were by then, but because time starts flowing at different rates in different parts of the world due to &quot;plot-reasons&quot;. Having abandoned strict time just before time gets wonky made things a lot worse.&lt;/p&gt;
&lt;p&gt;Robert Jordan uses strict time and POV switches in a clever way to avoid too big time jumps but at the same time to avoid dead time. Strictly increasing time doesn&#39;t prevent time jumps if the jumps are forward in time. Robert Jordan often did time jumps between books in Wheel of Time but tried to avoid very big ones in the middle of books. This can be a problem in this sort of medieval fantasy book because there is a lot of dead time while characters are travelling between location, mostly by ship or horse. Robert Jordan uses POV switches to mask this. For example: some POV heads off with a ship on a trip that will last a week. He masks this time by switching to some other POV and follow that for a week and then switch back once a week on time has passed.&lt;/p&gt;
&lt;p&gt;Related to how Robert Jordan handles dead time is how he switches between plot threads. Some authors, when switch plots threads, leave the previous plot thread on a cliffhanger. Cliffhangers on plot thread switches in books are like jump scares in movies. They reek of desperation. A good horror movie does not need jump scares to be scare. A good book does not need cliffhangers on switches between plot threads to keep the reader hooked. Robert Jordan usually stuck with the same plot thread for several chapters in a row, only switching away when the plot thread had reached some sort of resolution or at least a pause. This made each set of chapters following a single plot thread feel like a short story.&lt;/p&gt;
&lt;p&gt;One of the most important things Robert Jordan did to manage so many POVs was to introduce the character before the character was introduced as a POV. By having an existing POV get to know something about a new character before that character becomes a POV the reader also starts the new POV with some notion of how the new POV fits into the story. This also made plot lines branch out from one line in a tree type fashion, rather than dumping a bunch of unrelated plot lines on the reader and hoping the reader keeps them straight. Now, Robert Jordan did have different ways of introducing new soon-to-be POV characters. The most straight forward way was to have existing POV character meet and interact with a new character, and then, later, switch to that new characters POV. Another way he did it if the characters couldn&#39;t meet was to have an existing POV character hear about some new character before that new character became a POV. If he wanted to keep the new character mysterious he would have an existing character do something somewhere and then switch to a new POV watching the existing character covertly. That way there would still be some tie to an existing character to keep the branching structure in place but keep the reader in the dark about the new POV.&lt;/p&gt;
&lt;p&gt;To help smooth over POV switches Robert Jordan does something I call bridging. By this I mean that he keeps the thread of events ongoing across POV switches by starting off new POV after the switch following on from the last event of the old POV from before the switch. Let me give an example to make it clear what I am talking about. We are following POV character A and something happens and as a result the character decides to run off to deal with it. At this point the POV switches to another character B. It starts with POV character B reflecting on having just seen character A run off and continues with what B does after that. Because of strictly increasing time after the switch to character B cannot involve B seeing A run off, because that already happened for POV A, but it can still tie in to it by B reflecting on it. This way even though the POV switches, the chain of events remains unbroken, by having the new POV start of from where the previous POV left of. Robert Jordan mainly used this trick in two sorts of situations. One was when he did a lot of POV switches in one chapter between different POVs involved in the same events. The other is when switching to a new, never before seen, POV. Have some existing POV character meet a new character and interact with them. Then switch to new character&#39;s POV with the new character leaving the meeting and reflecting on it.&lt;/p&gt;
&lt;p&gt;These are not the only tricks Robert Jordan used to handle his many POVs in Wheel of Time, but these are the ones that stood out to me. It is also not like it is required to use tricks like these for handling multiple POVs in books, at least not when the number of POVs are limited. Once the number of POVs start increasing beyond three to four something extra becomes useful to help the reader handle them.&lt;/p&gt;
&lt;p&gt;The Wheel of Time series is remembered for how it drowned in POVs, which is a shame. It deserves to be remembered for how well it handled multiple POVs.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Raven&#39;s shadow - To fall so far</title>
        <published>2018-07-15T00:00:00+00:00</published>
        <updated>2018-07-15T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/raven-shadow/"/>
        <id>https://towerbabbel.com/raven-shadow/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/raven-shadow/">&lt;p&gt;Raven&#39;s Shadow is the first series by a new author Anthony Ryan. It’s a trilogy consisting of Blood Song, Tower Lord and Queen of Fire. It’s also a series which starts so great and end in such mediocrity.&lt;/p&gt;
&lt;p&gt;The first book is really one of the great works of Fantasy. The book is really great. Its set in a medieval fantasy world and is a single POV story following the protagonist Vaelin Al Sorna. He gets handed to a sort of templar like warring monk society as a child and the book covers his time growing up among the warrior monks and then how he ends up in the service of the king of the land. Being fantasy there is also some magic in play. Vaelin has a sort of magical gift, the titular Blood Song, which guides him, at least when he bothers to listen.&lt;/p&gt;
&lt;p&gt;The book also has a brilliant narrative setup where is sort of has two narrators. The prologue and epilogue is told from the point of view of a historian how follows a condemned criminal to his execution. On the way there he convinces the criminal to tell him his life story, so he can record it. The main narrative of the book is then the story of the criminal, Vaelin. When I started the book, I was a little worried about how well this would work in that the prologue sort of spoils the main story, but my worried were unfounded. In the end the meta-narrative of the historian and the life story of Vaelin come together beautifully. The ending is truly epic.&lt;/p&gt;
&lt;p&gt;After such a great start the second book, Tower Lord, is a big step down. This is not to say the say the second book is a bad book. It’s not. Rather it’s just that the first one is so great that you can have a big step down and still end up with a good book. Rather than being a single POV book like the first one, this one has multiple POVs. It also handles them in a way I just &lt;em&gt;loath&lt;/em&gt;: Jump between POVs and storylines every single damn chapter. It seems like it’s become quite popular lately. I blame George RR Marten. The good there is in A Song of Ice and Fire is good despite the constant jumping not because of it.&lt;/p&gt;
&lt;p&gt;The book also undermines the previous book&#39;s world building. Where Vaelin had to train from childhood to achieve his martial prowess, now there are characters popping up that are way too good for what training they have. Worst offender here is a new female character called Reva. Which is a shame, for aside from that she is the most interesting new character, and the only one with a proper character arc.&lt;/p&gt;
&lt;p&gt;If there was one weakness in the first book it was that the romance was kind flat and passionless. In the second book there is a new magically induced romance. Another flat and passionless romance, this time with a side dish of questionable consent. That does not improve things.&lt;/p&gt;
&lt;p&gt;Where the second book was still a good book, the third one, Queen of Fire, isn&#39;t even that. It is decidedly mediocre. There will be some minor spoilers ahead, but this book isn&#39;t worth reading anyway, so don&#39;t worry. It is time for the main characters to take the war to the Evil Empire. This war is really boring with short descriptions of uninteresting battles against mind-controller slave soldiers. They are like the worst evil overlord goons.&lt;/p&gt;
&lt;p&gt;To spice things up Vaelin loses his blood song ability. Cliched sure but could be interesting. How does the hero deal with losing his defining super power? But after moping about it a bit early in the book he runs into a woman with the same ability, so he just spends the rest of the book following her around instead. So, the entire plot point really doesn&#39;t lead to any interesting character growth or anything. He can just spend the rest of the book ignoring the issue. So, what does he do? Spends most of the book traipsing across a glacier just to get a big exposition dump in the end that explain everything about the big baddie. Who turn out to be boring.&lt;/p&gt;
&lt;p&gt;The most interesting character in the last book is Reva, and that&#39;s saying something considering that she has neither a character arc nor anything to do with the plot. Reva&#39;s character arc is basically complete by the end of the second book. There is some hope for something interesting when she adopts a girl early in the book, but after that the girl is never heard from again and has no bearing on the plot. She also has her own side plot that has nothing to do with the resolution of the main plot. She just sort of ends up at the same place as all the other characters in the end. But at least her sub-plot has interesting action and adventure, not just dry battle description or walking across a glacier.&lt;/p&gt;
&lt;p&gt;The ending still leaves a bunch of threads hanging. Like the how Vaelin never deals with losing the blood song. Reva&#39;s hunt for the priest from her childhood never goes anywhere. The wolf god thing is never explained. And the prophecy from the first book? Apparently just someone&#39;s pipe dream or something because it never leads anywhere.&lt;/p&gt;
&lt;p&gt;The last book is also the longest, and it &lt;em&gt;really&lt;/em&gt; feels like it. Plot-wise, you could just rip out both Reva and Vaelin, and just have someone else get the boring exposition dumps. That way you could at least cut the length of the book in half to tighten up the pacing. But honestly, it would still be boring.&lt;/p&gt;
&lt;p&gt;My recommendation is to read the first book, because it is really awesome. Then just skip the rest. Sure, that leaves a few plot threads hanging, but their resolution is boring and the final book has its own unresolved plot threads anyway, and the ending of the first book is way better than the end of the trilogy.&lt;/p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>The making of a blog</title>
        <published>2018-07-09T00:00:00+00:00</published>
        <updated>2018-07-09T00:00:00+00:00</updated>
        
        <author>
          <name>Unknown</name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://towerbabbel.com/making-a-blog/"/>
        <id>https://towerbabbel.com/making-a-blog/</id>
        
        <content type="html" xml:base="https://towerbabbel.com/making-a-blog/">&lt;p&gt;I figured the most navel-gazing way to start a new blog is to talk about how the blog was made.&lt;/p&gt;
&lt;p&gt;This blog is made with a static site generator, an (CLI) application that takes some content and templates and generates all the html/css files needed for the site offline. You then deploy the resulting files to any static files host. The means that you don&#39;t run any code on the server and don&#39;t have a database. The advantage of this is that you don&#39;t need to pay for any compute/db server side, and there is nothing that can be hacked or that needs to be administered. Also, because all pages are generated ahead of time its fast because there is no need to generate the pages as requests come in. The downsides are that the site is static, so there is no possibility for dynamic content like comments. (Unless you embed some third-party comment system like Facebook&#39;s.) The advantage of a static site generator over plain static sites is that you still get templates and stuff, so you don&#39;t need to copy/paste everything for every page on the site. Also saves you a lot of work for creating category pages and similar.&lt;/p&gt;
&lt;p&gt;The static site generator I ended up using is &lt;a rel=&quot;external&quot; href=&quot;https://www.getgutenberg.io/&quot;&gt;Gutenberg&lt;/a&gt;. This was not the result of some in depth investigation into all the static site generators out there. Rather it was something I had stumbled upon in a Reddit thread at some point that had been sitting in a half-forgotten tab ever since.&lt;/p&gt;
&lt;p&gt;Gutenberg appealed to me for a few different reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is a single statically compiled binary you can download from &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Keats/gutenberg/releases&quot;&gt;GitHub&lt;/a&gt; so there is no need to install any programming language runtime to get it working.&lt;/li&gt;
&lt;li&gt;It uses &lt;a rel=&quot;external&quot; href=&quot;https://tera.netlify.app/&quot;&gt;Tera&lt;/a&gt; as a templating language, which is based on Jinja2, and Sass for css. Since I use Jinja2 and Sass at my $dayjob I felt right at home.&lt;/li&gt;
&lt;li&gt;Content is written in markdown with a special header for to specify metadata.&lt;/li&gt;
&lt;li&gt;It has a local serve functionality where it will watch the filesystem for changes, and when it sees them it will recompile the site and refresh it in the browsers (via some injected js). It is fast enough that a recompile takes on the order of milliseconds.&lt;/li&gt;
&lt;li&gt;It has the concepts of shortcodes from WordPress, where you can define small snippets of templates that you can then call from a markdown content file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is one clear shortcoming I&#39;ve run into with Gutenberg so far: There is no way to globally access a list of categories. I wanted to have a list of category link in the sidebar, but I can&#39;t do that. You can even see an empty box in the sidebar where I wanted to put them. There is an open issue on &lt;a rel=&quot;external&quot; href=&quot;https://github.com/Keats/gutenberg/issues/246&quot;&gt;GitHub&lt;/a&gt; about User-defined taxonomies, which apparently should enable that as well.&lt;/p&gt;
&lt;p&gt;Gutenberg does have a theme system and a few existing themes, but I didn&#39;t use it. Instead I just hand rolled a few templates. The design is based around grey lines and rounded corners. This was originally driven by laziness. It is something that can be easily done in CSS so I wouldn&#39;t need to muck about with raster images (aside from the favicon). Given that I started on design centered around shades of grey I decided continue on that path and go for a monochrome look. For example, links are black (which is a bit darker than normal text) when unvisited but switch to a shade of grey when visited. I&#39;m also using the circle &lt;code&gt;ul&lt;/code&gt; list style because it fits in with the rest of the design. The one exception to the monochrome design is syntax highlighting, where is use an existing built in theme called &lt;code&gt;ir-white&lt;/code&gt;, that is light but still colored. It looks like this:&lt;/p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color: #24292E; background-color: #FFFFFF;&quot; &gt;&lt;code data-lang=&quot;rust&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #D73A49;&quot;&gt;fn&lt;/span&gt;&lt;span&gt; main () {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: #6F42C1;&quot;&gt;  println!&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span style=&quot;color: #032F62;&quot;&gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;span&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I also took the opportunity to finally get to play with css grids. This is something I&#39;ve been drooling over for a while but never been able to take into use due to the need to support Internet Explorer. This means this blog doesn&#39;t look great in IE11. It falls back to a boring looking single column layout, which works but isn&#39;t as pretty. The advantage of making a site for your own use is that you can just choose to ignore the IE11 users. :)&lt;/p&gt;
&lt;p&gt;For hosting I use &lt;a rel=&quot;external&quot; href=&quot;https://www.netlify.com/&quot;&gt;netlify&lt;/a&gt;, which works great with Gutenberg and GitHub. Just push a change to the master branch on GitHub and a git hook at netlify runs gutenberg and compiles the site and deploys the result. It also has nice features like deploying a preview of the site based on a branch. Simple support for custom domains and automatic TLS via Let&#39;s Encrypt. Oh, and you can&#39;t beat the price: $0/month. How do they pay for things? They have a lot of upsell to fancier features, but nothing I need for a simple static blog.&lt;/p&gt;
&lt;p&gt;Overall, I&#39;m really pleased with this setup. We&#39;ll see how long it lasts before I run into something it won&#39;t do for me, or just the urge to tinker becomes overwhelming.&lt;/p&gt;
</content>
        
    </entry>
</feed>
