<?xml version="1.0" encoding="UTF-8"?> <feed xmlns="http://www.w3.org/2005/Atom">
  <title>Krzysztof Kowalczyk blog</title>
  <link href="https://blog.kowalczyk.info/atom.xml" rel="alternate"></link>
  <id>https://blog.kowalczyk.info/atom.xml</id>
  <updated>2001-08-29T00:00:00Z</updated>
  <entry>
   <title>Speeding up JavaScript function with AI help</title>
   <link href="https://blog.kowalczyk.info/a-mjpn/speeding-up-javascript-function-with-ai-help.html" rel="alternate"></link>
   <updated>2026-03-29T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2026-03-29:/a-mjpn/speeding-up-javascript-function-with-ai-help.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;mjpn&#34;&gt;&#xA;&lt;div&gt;A new JavaScript library &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/chenglou/pretext&#34;&gt;pretext&lt;/a&gt; for fast text measuring / layout popped up on social media.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Potentially interesting given its focus on speeding up text rendering in web apps and me writing web apps and liking them being fast.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I looked at the code and saw a function &lt;code&gt;isCJK()&lt;/code&gt;. Given my 3 decades of programming and performance optimization, it looked like it could be sped up.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This is a story about ideas on making JavaScript faster and the process of quickly implementing and benchmarking them.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;the-code&#34;&gt;&lt;div&gt;The code&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#the-code&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;isCJK&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;boolean&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ch&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;codePointAt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x4E00&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x9FFF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x3400&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x4DBF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x20000&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2A6DF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2A700&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2B73F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2B740&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2B81F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2B820&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2CEAF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2CEB0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2EBEF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30000&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x3134F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xF900&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xFAFF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2F800&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x2FA1F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x3000&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x303F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x3040&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x309F&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30A0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30FF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xAC00&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xD7AF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xFF00&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xFFEF&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;my-spider-sense-tingling&#34;&gt;&lt;div&gt;My spider sense tingling&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#my-spider-sense-tingling&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;To make code run fast you have to have mechanical sympathy. You need a good mental model of how CPUs and programming languages work, at the low level.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Because I have mechanical sympathy, I know that to evaluate multiple &lt;code&gt;||&lt;/code&gt; statements, the program has to check every statement until it finds one that is true.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For the case of not matching any range, it has to do all 15 comparisons.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;My immediate thought was that most characters are ascii (non-cjk) and therefore require 15 comparisons.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;An early exit should speed things up: &lt;code&gt;if (c &amp;lt; 0x300) continue;&lt;/code&gt;. It adds 1 comparison for matching cases but removes 14 (15 - 1) for the most common case of ascii characters.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;hunch-is-good-benchmark-is-better&#34;&gt;&lt;div&gt;Hunch is good, benchmark is better&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#hunch-is-good-benchmark-is-better&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Micro-benchmarking is subtle. In the past I would google for a JavaScript benchmarking library and trust that it&amp;rsquo;s sound.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Claude wrote a sound, simple benchmark function:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;bench&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;iterations&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1_000_000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;10_000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// warmup&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;performance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;iterations&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fn&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;elapsed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;performance&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;now&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;start&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;opsPerSec&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;iterations&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;/&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;elapsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;toFixed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;: &lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;elapsed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;toFixed&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt; ms (&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;opsPerSec&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt; ops/sec)`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// to call:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;bench&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;isCJKRegex       &amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;isCJKRegex&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;input&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;));&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;The subtle part is warmup phase.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;JavaScript JIT engines that you&amp;rsquo;re likely to use (&lt;a target=&#34;_blank&#34; href=&#34;https://v8.dev/&#34;&gt;v8&lt;/a&gt; in Chrome, &lt;a target=&#34;_blank&#34; href=&#34;https://docs.webkit.org/Deep%20Dive/JSC/JavaScriptCore.html&#34;&gt;JavaScriptCore&lt;/a&gt; in Safari, &lt;a target=&#34;_blank&#34; href=&#34;https://spidermonkey.dev/&#34;&gt;SpiderMonkey&lt;/a&gt; in FireFox) have several optimization tiers and only do most aggressive optimization for frequently called functions.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The warmup phase forces JIT to compile &lt;code&gt;fn&lt;/code&gt; with most aggressive settings.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This is only fair - I assume &lt;code&gt;isCJK&lt;/code&gt; is called frequently. If it wasn&amp;rsquo;t, there&amp;rsquo;s no point sweating to optimize it.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;the-new-ai-normal&#34;&gt;&lt;div&gt;The new AI normal&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#the-new-ai-normal&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;In the past I would have to manually implement each optimization idea.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;With AI I can delegate the coding and therefore test more ideas.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The following was done with Claude 4.6.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;100-vibe-coding&#34;&gt;&lt;div&gt;100% vibe coding&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#100-vibe-coding&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;There are levels of delegating things to AI. On the extreme side of giving up control is 100% vibe coding.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I had 2 ideas for performance optimization:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;early exit&lt;/li&gt;&#xA;&lt;li&gt;replace 15 linear checks with binary search&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;But what if I didn&amp;rsquo;t? What if I just ask AI to come up with ideas?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The following is my conversation with Claude 4.6 and what I&amp;rsquo;ve learned.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I created &lt;code&gt;is_cjk.js&lt;/code&gt; file and pasted the original function.&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;look at is_cjk.js. come up with 2 ideas for how to speed up isCJK(). Implement those as separate functions and write a javascript micro-benchmark that compares those 2 new implementations against isCJK&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Two ideas:&lt;/div&gt;&#xA;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;Pre-compiled regex — push the entire check into the native regex engine, avoiding JS-level for&amp;hellip;of&#xA;iteration and codePointAt() overhead.&lt;/li&gt;&#xA;&lt;li&gt;Typed array bitmap for BMP — for BMP characters (the vast majority of real text), a Uint8Array bitmap&#xA;gives O(1) lookup with a single array access. Fall back to range checks only for supplementary plane&#xA;characters.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;I have to admit: I recognize those as valid optimization ideas but they didn&amp;rsquo;t immediately occur to me.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Regex works because regex implementations in JavaScript engines are insanely optimized.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Bitmap is a known optimization for doing true/false lookup for numbers. Let&amp;rsquo;s say you have total range 0-255 and you want a function that checks if a number is in range 1-10, 20-30, 40-50, 60-70, 80-90. That&amp;rsquo;s 5 if statements, each doing 2 comparisons.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You can instead use 1 bit for each of the 256 numbers (i.e. &lt;sup&gt;256&lt;/sup&gt;&amp;frasl;&lt;sub&gt;8&lt;/sub&gt; = 32 bytes), pre-compute the array of bytes and set the bit for the ranges.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Then lookup is just math to get byte offset and bit, load the byte, check the bit. Super fast.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Claude not only wrote the benchmark function, 2 new implementations but also ran the benchmarks using node and showed me results in a readable way.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The bitmap approach was significantly faster.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;human-assisted-coding&#34;&gt;&lt;div&gt;Human assisted coding&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#human-assisted-coding&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Bitmap was the fastest and yet I discarded it using my human judgement.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The bitmap needed 65kB of memory and that&amp;rsquo;s just too much for this function.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That&amp;rsquo;s where human judgement comes in to improve collaboration with AI.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I didn&amp;rsquo;t specify that I also care about memory usage so AI wrote fast code that was using too much memory.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;you-re-benchmarking-what&#34;&gt;&lt;div&gt;You&amp;rsquo;re benchmarking what?&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#you-re-benchmarking-what&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Here&amp;rsquo;s another tricky part of benchmarking: knowing what you benchmark.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;There are 3 popular JavaScript engines. Claude ran benchmarks using &lt;code&gt;node&lt;/code&gt; which uses Chrome&amp;rsquo;s v8.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That&amp;rsquo;s good because that&amp;rsquo;s the most popular browser and therefore most popular JavaScript JIT engine.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s also good to sanity-check with at least one other JavaScript engine. &lt;code&gt;bun&lt;/code&gt; uses Safari&amp;rsquo;s JavaScriptCore so I asked Claude:&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;run the tests using bun&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;The results were similar, which is good. We don&amp;rsquo;t want code that is fast in one engine but slow in another. We don&amp;rsquo;t control which browser the user of our code is running.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;continuing-collaboration-with-ai&#34;&gt;&lt;div&gt;Continuing collaboration with AI&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#continuing-collaboration-with-ai&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;I had some more ideas so here&amp;rsquo;s the rest of my conversation with Claude.&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;don&amp;rsquo;t benchmark bitmap, it uses too much memory; write a variant of isCJK that does an early false exit&#xA;if char is less than smallest&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;Early exit is my first insight I wanted to test.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;As expected, early exit is good 2x speedup for latin strings, although regex beats it on cjk strings.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That is the curse of engineering trade-offs: you have to decide if you want to optimize for cjk strings or non-cjk strings.&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;now implement a variant that does inline bisect / binary search&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;That was my second idea: do a binary search instead of sequential &lt;code&gt;if&lt;/code&gt; comparisons.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It was faster than original but slower than regex / early exit.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Also, Claude didn&amp;rsquo;t do what I meant. It stored the ranges as array:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Flat array: [lo0, hi0, lo1, hi1, ...] sorted by lo&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;cjkRanges&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Uint32Array&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;mh&#34;&gt;0x3000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x303f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;mh&#34;&gt;0x3040&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x309f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;That&amp;rsquo;s what I meant:&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;implement a variant isCJBisect that doesn&amp;rsquo;t use array but unrolls binary search logic into if statements&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;The implementation is gnarly:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;inCJKUnrolled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x3000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0xff00&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x3400&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x3040&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x303f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;else&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x309f&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30a0&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;c&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&#34;mh&#34;&gt;0x30ff&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ... more gnarly code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;But what do I care? Claude wrote it. Arguably it&amp;rsquo;s hard for me to review for correctness but it&amp;rsquo;s perfectly testable. We can write a test to compare if it returns the same result as original function for every possible input.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;As expected, unrolled version was faster than array-based but not always faster than regex or early exit.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;But Claude wrote something that caught my eye:&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;The for&amp;hellip;of + codePointAt iterator overhead remains the bottleneck shared by all non-regex variants on&#xA;  long strings.&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s well known that &lt;code&gt;for ... of&lt;/code&gt; loop is slower than &lt;code&gt;for (let i = 0; i &amp;lt; n; i++)&lt;/code&gt;. It&amp;rsquo;s one of those things that you need to know.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I knew this but I didn&amp;rsquo;t connect the dots in this particular case.&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;write variant of isCJKEarly which replaces for of with a faster loop&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;Result:&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;isCJKEarlyFast crushes everything across the board on both runtimes&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;The code for &lt;a target=&#34;_blank&#34; href=&#34;https://gist.github.com/kjk/bdbea9d90c3bb0454fbe26353c521bfd#file-is_cjk-js-L38&#34;&gt;isCKJEarlyFast&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Looks like we have a winner:&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;Replacing for&amp;hellip;of + codePointAt() with charCodeAt() + index loop eliminates the iterator overhead, which was the main bottleneck. The early c &amp;lt; 0x3000 bail then skips all range checks for ASCII/latin characters cheaply. Only regex still wins on Node&amp;rsquo;s long latin miss case thanks to V8&amp;rsquo;s native string scanning.&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;There&amp;rsquo;s a subtlety that makes the rewrite of &lt;code&gt;for .. of&lt;/code&gt; into &lt;code&gt;for (let i = 0; i &amp;lt; n; i++)&lt;/code&gt; tricky.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Logically JavaScript strings are composed from 16-bit numbers (characters). Some Unicode code-points are bigger than 16-bit and are stored as 2 16-bit numbers, called surrogate pairs.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;So writing a loop over unicode codepoints needs to take this into account.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s tricky code but again, what do I care? Claude wrote it and it&amp;rsquo;s perfectly testable.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;pressing-on&#34;&gt;&lt;div&gt;Pressing on&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#pressing-on&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;The good thing about claude writing most of the code and removing other tedium like running the benchmarks is that we can do more in the same amount of time.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;So I explored even more.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I noticed:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;isCJKUnrolled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;ch&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;inCJKUnrolled&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;codePointAt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)))&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;What happens when &lt;code&gt;inCJKUnrolled&lt;/code&gt; is inlined?&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;inline inCJKUnrolled into isCJKUnrolled&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;Result:&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;Done. Inlining didn&amp;rsquo;t help — it actually got slightly slower in most cases (the engine was already inlining the small function). No change in rankings; EarlyFast remains the winner.&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;Turns out it&amp;rsquo;s not faster, which was surprising. Inlining is supposed to remove overhead of function calls, which matters in loops.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Surprising isn&amp;rsquo;t bad. We run benchmarks to validate our hunches.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For completness, I wanted to compare with original where &lt;code&gt;for .. of&lt;/code&gt; was rewritten.&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;also write original with for of replaced by standard for loop and bench all and give results as markdown table&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;Claude was nice enough to show benchmark results in a nicely formatted table, without me even asking. It just knows things.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;But as you can see above, you can ask it for results in markdown table to e.g. include in a GitHub bug report.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Here are final results. The number is operations/second in millions. Higher is better.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;bun&#34;&gt;&lt;div&gt;Bun&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#bun&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th&gt;Scenario&lt;/th&gt;&#xA;&lt;th&gt;Original&lt;/th&gt;&#xA;&lt;th&gt;Regex&lt;/th&gt;&#xA;&lt;th&gt;Early&lt;/th&gt;&#xA;&lt;th&gt;Bisect&lt;/th&gt;&#xA;&lt;th&gt;Unrolled&lt;/th&gt;&#xA;&lt;th&gt;EarlyFast&lt;/th&gt;&#xA;&lt;th&gt;ForLoop&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Single CJK&lt;/td&gt;&#xA;&lt;td&gt;11M&lt;/td&gt;&#xA;&lt;td&gt;22M&lt;/td&gt;&#xA;&lt;td&gt;12M&lt;/td&gt;&#xA;&lt;td&gt;12M&lt;/td&gt;&#xA;&lt;td&gt;16M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;79M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;td&gt;57M&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Single latin&lt;/td&gt;&#xA;&lt;td&gt;20M&lt;/td&gt;&#xA;&lt;td&gt;24M&lt;/td&gt;&#xA;&lt;td&gt;49M&lt;/td&gt;&#xA;&lt;td&gt;21M&lt;/td&gt;&#xA;&lt;td&gt;22M&lt;/td&gt;&#xA;&lt;td&gt;40M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;36M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;CJK string&lt;/td&gt;&#xA;&lt;td&gt;12M&lt;/td&gt;&#xA;&lt;td&gt;18M&lt;/td&gt;&#xA;&lt;td&gt;17M&lt;/td&gt;&#xA;&lt;td&gt;12M&lt;/td&gt;&#xA;&lt;td&gt;14M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;42M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;td&gt;42M&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Latin string&lt;/td&gt;&#xA;&lt;td&gt;1.5M&lt;/td&gt;&#xA;&lt;td&gt;4.7M&lt;/td&gt;&#xA;&lt;td&gt;3.6M&lt;/td&gt;&#xA;&lt;td&gt;3.0M&lt;/td&gt;&#xA;&lt;td&gt;3.5M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;17M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;td&gt;6.5M&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Mixed string&lt;/td&gt;&#xA;&lt;td&gt;6.5M&lt;/td&gt;&#xA;&lt;td&gt;5.9M&lt;/td&gt;&#xA;&lt;td&gt;9.9M&lt;/td&gt;&#xA;&lt;td&gt;8.6M&lt;/td&gt;&#xA;&lt;td&gt;13M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;62M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;td&gt;34M&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;node&#34;&gt;&lt;div&gt;Node&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#node&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;table&gt;&#xA;&lt;thead&gt;&#xA;&lt;tr&gt;&#xA;&lt;th&gt;Scenario&lt;/th&gt;&#xA;&lt;th&gt;Original&lt;/th&gt;&#xA;&lt;th&gt;Regex&lt;/th&gt;&#xA;&lt;th&gt;Early&lt;/th&gt;&#xA;&lt;th&gt;Bisect&lt;/th&gt;&#xA;&lt;th&gt;Unrolled&lt;/th&gt;&#xA;&lt;th&gt;EarlyFast&lt;/th&gt;&#xA;&lt;th&gt;ForLoop&lt;/th&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/thead&gt;&#xA;&#xA;&lt;tbody&gt;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Single CJK&lt;/td&gt;&#xA;&lt;td&gt;85M&lt;/td&gt;&#xA;&lt;td&gt;54M&lt;/td&gt;&#xA;&lt;td&gt;51M&lt;/td&gt;&#xA;&lt;td&gt;44M&lt;/td&gt;&#xA;&lt;td&gt;56M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;112M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;td&gt;110M&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Single latin&lt;/td&gt;&#xA;&lt;td&gt;59M&lt;/td&gt;&#xA;&lt;td&gt;72M&lt;/td&gt;&#xA;&lt;td&gt;83M&lt;/td&gt;&#xA;&lt;td&gt;55M&lt;/td&gt;&#xA;&lt;td&gt;74M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;115M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;td&gt;103M&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;CJK string&lt;/td&gt;&#xA;&lt;td&gt;79M&lt;/td&gt;&#xA;&lt;td&gt;55M&lt;/td&gt;&#xA;&lt;td&gt;60M&lt;/td&gt;&#xA;&lt;td&gt;55M&lt;/td&gt;&#xA;&lt;td&gt;64M&lt;/td&gt;&#xA;&lt;td&gt;90M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;129M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Latin string&lt;/td&gt;&#xA;&lt;td&gt;4.2M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;57M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;td&gt;4.3M&lt;/td&gt;&#xA;&lt;td&gt;2.8M&lt;/td&gt;&#xA;&lt;td&gt;4.5M&lt;/td&gt;&#xA;&lt;td&gt;12M&lt;/td&gt;&#xA;&lt;td&gt;8.3M&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&#xA;&lt;tr&gt;&#xA;&lt;td&gt;Mixed string&lt;/td&gt;&#xA;&lt;td&gt;14M&lt;/td&gt;&#xA;&lt;td&gt;15M&lt;/td&gt;&#xA;&lt;td&gt;16M&lt;/td&gt;&#xA;&lt;td&gt;10M&lt;/td&gt;&#xA;&lt;td&gt;15M&lt;/td&gt;&#xA;&lt;td&gt;&lt;strong&gt;41M&lt;/strong&gt;&lt;/td&gt;&#xA;&lt;td&gt;38M&lt;/td&gt;&#xA;&lt;/tr&gt;&#xA;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;conclusions&#34;&gt;&lt;div&gt;Conclusions&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#conclusions&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;AI is a big unlock. It took me under 30 minutes to test various hypotheses and find out a significant speed up.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Without Claude it would take several hours and I would likely not do it at all. It&amp;rsquo;s just not important enough to spend a working day on it.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To get best results we still need to apply human judgement and guide the AI.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;programming-expert-knowledge&#34;&gt;&lt;div&gt;Programming expert knowledge&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#programming-expert-knowledge&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;An expert is simply someone who knows things. We know things because we learn them.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If you were paying attention you might have learned the following things:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;importance of warmup phase when benchmarking JIT compilers&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;for .. of&lt;/code&gt; is slower than &lt;code&gt;for (let i = 0; i &amp;lt; n; i++)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;regex matching in JavaScript engines is fast&lt;/li&gt;&#xA;&lt;li&gt;subtlety of surrogate pairs in JavaScript strings&lt;/li&gt;&#xA;&lt;li&gt;using bitmaps to speed up range lookups&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;resources&#34;&gt;&lt;div&gt;Resources&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#resources&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;All the code is in &lt;a target=&#34;_blank&#34; href=&#34;https://gist.github.com/kjk/bdbea9d90c3bb0454fbe26353c521bfd&#34;&gt;https://gist.github.com/kjk/bdbea9d90c3bb0454fbe26353c521bfd&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I like to write fast code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If you want a fast bookmark manager / note taker, try &lt;a target=&#34;_blank&#34; href=&#34;https://marklexis.arslexis.io&#34;&gt;MarkLexis&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If you want a fast PDF / ebook / comic book reader for Windows, try &lt;a target=&#34;_blank&#34; href=&#34;https://www.sumatrapdfreader.org/free-pdf-reader.html&#34;&gt;SumatraPDF&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>How to run msvc cl.exe from command-line (powershell)</title>
   <link href="https://blog.kowalczyk.info/til-how-to-run-msvc-cl.exe-from-command-line-powershell.html" rel="alternate"></link>
   <updated>2026-01-16T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2026-01-16:/til-how-to-run-msvc-cl.exe-from-command-line-powershell.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-how-to-run-msvc-cl.exe-from-command-line-powershell&#34;&gt;&#xA;&lt;div&gt;So you&amp;rsquo;ve installed Visual Studio and you want to run the compiler &lt;code&gt;cl.exe&lt;/code&gt; from command-line. Microsoft makes it surprisingly hard.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;They give you a shortcut which opens a terminal window with &lt;code&gt;cmd.exe&lt;/code&gt; setup for compilation. But I don&amp;rsquo;t want a separate window, I want to use the terminal app.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You can run:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;cmd.exe /k &amp;quot;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\Build\vcvarsall.bat&amp;quot; x64&lt;/code&gt; for VS 2022&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cmd.exe /k &amp;quot;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsall.bat&amp;quot; x64&lt;/code&gt; for VS 2026&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;Your location can be different.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;But I don&amp;rsquo;t want to run inside &lt;code&gt;cmd.exe&lt;/code&gt;. I want to use &lt;code&gt;powershell&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;What does &lt;code&gt;vcvarsall.bat&lt;/code&gt; do? Not much: it just sets some env variables and updates &lt;code&gt;PATH&lt;/code&gt; env variable.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We can reverse-engineer what it does:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;cmd.exe&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;set &amp;gt;before.txt&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;cmd.exe /k &amp;quot;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\Build\vcvarsall.bat&amp;quot; x64&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;set &amp;gt;after.txt&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;Now compare &lt;code&gt;before.txt&lt;/code&gt; and &lt;code&gt;after.txt&lt;/code&gt; to see what changed. I asked AI to do it for me and here&amp;rsquo;s the beginning of what I found:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CommandPromptType=Native&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DevEnvDir=C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ExtensionSdkDir=C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;EXTERNAL_INCLUDE=C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\shared;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\cppwinrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Framework40Version=v4.0&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FrameworkDir=C:\Windows\Microsoft.NET\Framework64\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;FrameworkDir64=C:\Windows\Microsoft.NET\Framework64\&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;... more stuff&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;I saved that to &lt;code&gt;diff.txt&lt;/code&gt; file.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Now that we have that we can ask our friendly AI to convert this to a powershell function:&lt;/div&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;write powershell function that sets variables as seen in &lt;code&gt;@diff.txt&lt;/code&gt;&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;I get something like this:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;set-msvc&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;&amp;lt;#&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;SYNOPSIS&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        Sets Visual Studio Developer Command Prompt environment variables.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;DESCRIPTION&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        This function sets all the environment variables needed for Visual Studio 2022&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        native x64 development, equivalent to running vcvars64.bat.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;EXAMPLE&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        Set-VsDevEnv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    #&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;CmdletBinding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;param&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:CommandPromptType&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Native&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:DevEnvDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;more&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;stuff&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;We need to change one thing: &lt;code&gt;$env:PATH&lt;/code&gt; from absolute to just adding paths to current &lt;code&gt;$env:PATH&lt;/code&gt; so that it&amp;rsquo;ll adapt to future changes in &lt;code&gt;PATH&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Now add that to &lt;code&gt;$PROFILE&lt;/code&gt; and you can type &lt;code&gt;set-msvc&lt;/code&gt; to setup powershell to have access to &lt;code&gt;cl.exe&lt;/code&gt;, &lt;code&gt;msbuild&lt;/code&gt; and other tools.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Below is the whole function but note that this is only for amd64 toolset. For 32-bit or arm setup would be different. You can get by re-running the above logic for vcvarsall.bat with different arguments.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This is for VS 2026&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;set-msvc&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;&amp;lt;#&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;SYNOPSIS&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        Sets Visual Studio Developer Command Prompt environment variables.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;DESCRIPTION&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        This function sets all the environment variables needed for Visual Studio 18&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        native x64 development, equivalent to running vcvars64.bat.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;EXAMPLE&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        Set-VsDevEnv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    #&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;CmdletBinding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;param&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:CommandPromptType&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Native&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:DevEnvDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:ExtensionSdkDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:EXTERNAL_INCLUDE&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\include;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\include;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\VS\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\shared;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\cppwinrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:Framework40Version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;v4.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FrameworkDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Windows\Microsoft.NET\Framework64\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FrameworkDir64&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Windows\Microsoft.NET\Framework64\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FrameworkVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;v4.0.30319&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FrameworkVersion64&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;v4.0.30319&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FSHARPINSTALLDIR&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:HTMLHelpDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\HTML Help Workshop&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:INCLUDE&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\include;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\include;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Auxiliary\VS\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\shared;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\cppwinrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:is_x64_arch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:LIB&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\x64;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\lib\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x64;C:\Program Files (x86)\Windows Kits\10\lib\10.0.26100.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\\lib\10.0.26100.0\\um\x64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:LIBPATH&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\x64;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\lib\x64;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\lib\x86\store\references;C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.26100.0;C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0;C:\Windows\Microsoft.NET\Framework64\v4.0.30319&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:NETFXSDKDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:Path&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\VC\VCPackages;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer;C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\bin\Roslyn;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64\;C:\Program Files (x86)\HTML Help Workshop;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools;C:\Program Files\Microsoft Visual Studio\18\Community\Team Tools\DiagnosticsHub\Collector;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\Llvm\x64\bin;C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\\x64;C:\Program Files (x86)\Windows Kits\10\bin\\x64;C:\Program Files\Microsoft Visual Studio\18\Community\\MSBuild\Current\Bin\amd64;C:\Windows\Microsoft.NET\Framework64\v4.0.30319;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\Tools\;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$env:Path&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\VC\Linux\bin\ConnectionManagerExe;C:\Program Files\Microsoft Visual Studio\18\Community\VC\vcpkg&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:Platform&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:UCRTVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;10.0.26100.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:UniversalCRTSdkDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCIDEInstallDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\VC\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCINSTALLDIR&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCPKG_ROOT&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\vcpkg&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCToolsInstallDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.44.35207\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCToolsRedistDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\VC\Redist\MSVC\14.44.35112\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCToolsVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;14.44.35207&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VisualStudioVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;17.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VS170COMNTOOLS&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\Common7\Tools\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSCMD_ARG_app_plat&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Desktop&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSCMD_ARG_HOST_ARCH&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSCMD_ARG_TGT_ARCH&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSCMD_VER&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;17.14.24&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSINSTALLDIR&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\18\Community\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsLibPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.26100.0;C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSdkBinPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\bin\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSdkDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSDKLibVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;10.0.26100.0\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSdkVerBinPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSDKVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;10.0.26100.0\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSDK_ExecutablePath_x64&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSDK_ExecutablePath_x86&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:__DOTNET_ADD_64BIT&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:__DOTNET_PREFERRED_BITNESS&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:__VSCMD_PREINIT_PATH&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\PowerShell\7;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Microsoft VS Code\bin;c:\Users\kjk\AppData\Local\Programs\cursor\resources\app\bin;C:\Program Files\gs\gs10.03.1\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\GitHub CLI\;C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\;C:\Program Files\Rust stable MSVC 1.88\bin;C:\Program Files\PowerShell\7\;C:\Program Files\nodejs\;C:\Program Files\dotnet\;C:\Program Files\CMake\bin;C:\Program Files\Go\bin;C:\Program Files\RedHat\Podman\;C:\Program Files\Tailscale\;C:\Program Files\Git\cmd;C:\Program Files\Docker\Docker\resources\bin;C:\Users\kjk\AppData\Local\Microsoft\WindowsApps;C:\Users\kjk\AppData\Local\Microsoft\WinGet\Links;C:\Users\kjk\.bun\bin;C:\Users\kjk\.dotnet\tools;C:\Users\kjk\go\bin;C:\Users\kjk\AppData\Local\Programs\superfile\;C:\Users\kjk\AppData\Local\Microsoft\WindowsApps;C:\Users\kjk\AppData\Local\GitHubDesktop\bin;C:\Users\kjk\AppData\Local\Programs\cursor\resources\app\bin;C:\Users\kjk\AppData\Roaming\npm;C:\Users\kjk\.dotnet\tools;C:\Users\kjk\AppData\Local\Programs\Antigravity\bin;C:\Users\kjk\AppData\Local\Programs\Zed\bin;C:\Users\kjk\go\bin;C:\Users\kjk\OneDrive\bin;C:\Users\kjk\.bin\jai\bin;C:\Users\kjk\.bin\mupdf-1.27.0;C:\Users\kjk\.local\bin;C:\Users\kjk\AppData\Local\Programs\WinMerge;C:\Users\kjk\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\Scripts;C:\Users\kjk\OneDrive\bin\sublime_text&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;Write-Host&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Visual Studio 2026 Developer Environment configured for x64.&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-ForegroundColor&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Green&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;This is for VS 2022:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;set-msvc&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cm&#34;&gt;&amp;lt;#&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;SYNOPSIS&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        Sets Visual Studio Developer Command Prompt environment variables.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;DESCRIPTION&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        This function sets all the environment variables needed for Visual Studio 2022&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        native x64 development, equivalent to running vcvars64.bat.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    .&lt;/span&gt;&lt;span class=&#34;sd&#34;&gt;EXAMPLE&lt;/span&gt;&lt;span class=&#34;cm&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;        Set-VsDevEnv&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cm&#34;&gt;    #&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;CmdletBinding&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;param&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:CommandPromptType&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Native&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:DevEnvDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:ExtensionSdkDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Microsoft SDKs\Windows Kits\10\ExtensionSDKs&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:EXTERNAL_INCLUDE&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\shared;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\cppwinrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:Framework40Version&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;v4.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FrameworkDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Windows\Microsoft.NET\Framework64\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FrameworkDir64&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Windows\Microsoft.NET\Framework64\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FrameworkVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;v4.0.30319&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FrameworkVersion64&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;v4.0.30319&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:FSHARPINSTALLDIR&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:HTMLHelpDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\HTML Help Workshop&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:INCLUDE&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\include;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Auxiliary\VS\include;C:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\ucrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\um;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\shared;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\winrt;C:\Program Files (x86)\Windows Kits\10\\include\10.0.26100.0\\cppwinrt;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\include\um&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:is_x64_arch&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;true&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:LIB&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\x64;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\lib\x64;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\lib\um\x64;C:\Program Files (x86)\Windows Kits\10\lib\10.0.26100.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\\lib\10.0.26100.0\\um\x64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:LIBPATH&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\ATLMFC\lib\x64;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\lib\x64;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\lib\x86\store\references;C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.26100.0;C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0;C:\Windows\Microsoft.NET\Framework64\v4.0.30319&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:NETFXSDKDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\NETFXSDK\4.8\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:Path&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\bin\HostX64\x64;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\VC\VCPackages;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TestWindow;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer;C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\bin\Roslyn;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64\;C:\Program Files (x86)\HTML Help Workshop;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools;C:\Program Files\Microsoft Visual Studio\2022\Community\Team Tools\DiagnosticsHub\Collector;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\Llvm\x64\bin;C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\\x64;C:\Program Files (x86)\Windows Kits\10\bin\\x64;C:\Program Files\Microsoft Visual Studio\2022\Community\\MSBuild\Current\Bin\amd64;C:\Windows\Microsoft.NET\Framework64\v4.0.30319;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\;&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$env:Path&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\VC\Linux\bin\ConnectionManagerExe;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\vcpkg&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:Platform&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:UCRTVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;10.0.26100.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:UniversalCRTSdkDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCIDEInstallDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\VC\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCINSTALLDIR&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCPKG_ROOT&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\vcpkg&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCToolsInstallDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.44.35207\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCToolsRedistDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Redist\MSVC\14.44.35112\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VCToolsVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;14.44.35207&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VisualStudioVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;17.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VS170COMNTOOLS&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSCMD_ARG_app_plat&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Desktop&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSCMD_ARG_HOST_ARCH&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSCMD_ARG_TGT_ARCH&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;x64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSCMD_VER&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;17.14.24&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:VSINSTALLDIR&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\Microsoft Visual Studio\2022\Community\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsLibPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.26100.0;C:\Program Files (x86)\Windows Kits\10\References\10.0.26100.0&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSdkBinPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\bin\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSdkDir&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSDKLibVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;10.0.26100.0\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSdkVerBinPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSDKVersion&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;10.0.26100.0\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSDK_ExecutablePath_x64&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\x64\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:WindowsSDK_ExecutablePath_x86&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.8 Tools\&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:__DOTNET_ADD_64BIT&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;1&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:__DOTNET_PREFERRED_BITNESS&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;64&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nv&#34;&gt;$env:__VSCMD_PREINIT_PATH&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;C:\Program Files\PowerShell\7;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\Microsoft VS Code\bin;c:\Users\kjk\AppData\Local\Programs\cursor\resources\app\bin;C:\Program Files\gs\gs10.03.1\bin;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Program Files\GitHub CLI\;C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\;C:\Program Files\Rust stable MSVC 1.88\bin;C:\Program Files\PowerShell\7\;C:\Program Files\nodejs\;C:\Program Files\dotnet\;C:\Program Files\CMake\bin;C:\Program Files\Go\bin;C:\Program Files\RedHat\Podman\;C:\Program Files\Tailscale\;C:\Program Files\Git\cmd;C:\Program Files\Docker\Docker\resources\bin;C:\Users\kjk\AppData\Local\Microsoft\WindowsApps;C:\Users\kjk\AppData\Local\Microsoft\WinGet\Links;C:\Users\kjk\.bun\bin;C:\Users\kjk\.dotnet\tools;C:\Users\kjk\go\bin;C:\Users\kjk\AppData\Local\Programs\superfile\;C:\Users\kjk\AppData\Local\Microsoft\WindowsApps;C:\Users\kjk\AppData\Local\GitHubDesktop\bin;C:\Users\kjk\AppData\Local\Programs\cursor\resources\app\bin;C:\Users\kjk\AppData\Roaming\npm;C:\Users\kjk\.dotnet\tools;C:\Users\kjk\AppData\Local\Programs\Antigravity\bin;C:\Users\kjk\AppData\Local\Programs\Zed\bin;C:\Users\kjk\go\bin;C:\Users\kjk\OneDrive\bin;C:\Users\kjk\.bin\jai\bin;C:\Users\kjk\.bin\mupdf-1.27.0;C:\Users\kjk\.local\bin;C:\Users\kjk\AppData\Local\Programs\WinMerge;C:\Users\kjk\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\LocalCache\local-packages\Python312\Scripts;C:\Users\kjk\OneDrive\bin\sublime_text&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;Write-Host&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Visual Studio 2022 Developer Environment configured for x64.&amp;#34;&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-ForegroundColor&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;Green&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Novel login system for web apps</title>
   <link href="https://blog.kowalczyk.info/til-novel-login-system-for-web-apps.html" rel="alternate"></link>
   <updated>2025-12-22T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-12-22:/til-novel-login-system-for-web-apps.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-novel-login-system-for-web-apps&#34;&gt;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://annas-archive.li/blog/&#34;&gt;Anna&amp;rsquo;s Archive&lt;/a&gt; implements an interesting, anonymous way to create an account for web applications.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;They don&amp;rsquo;t use e-mail, Google or GitHub logins. When you create an account, they generate a secret key. That secret key is used to login.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The downside is that if you loose they, you loose access to the account.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The interesting thing is anonymity: the operator of the web app doesn&amp;rsquo;t even have your e-mail address.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This is one of those things that are obvious once you learn it but would be very hard to come up on your own because thinking outside of the box is very hard.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Benchmarking JSON vs TOON in Go</title>
   <link href="https://blog.kowalczyk.info/til-benchmarking-json-vs-toon-in-go.html" rel="alternate"></link>
   <updated>2025-12-15T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-12-15:/til-benchmarking-json-vs-toon-in-go.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-benchmarking-json-vs-toon-in-go&#34;&gt;&#xA;&lt;div&gt;Since I&amp;rsquo;ve decided to use &lt;a target=&#34;_blank&#34; href=&#34;https://toonformat.dev/&#34;&gt;TOON&lt;/a&gt; instead of JSON, I&amp;rsquo;ve benchmarked the performance of serialization of 2 Go TOON libraries compared to JSON built-in serialization.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Here are the results using current version of the libraries and go 1.25:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;% go run .&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goos: darwin&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goarch: arm64&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pkg: bench_toon&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cpu: Apple M3 Pro&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BenchmarkJSONMarshalCompact-11    &#x9; 3488496&#x9;       322.3 ns/op&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BenchmarkJSONMarshal-11           &#x9;  767379&#x9;      1546 ns/op&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BenchmarkToonMarshal-11           &#x9;  669687&#x9;      1782 ns/op&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;BenchmarkGotoonEncode-11          &#x9;  161412&#x9;      7506 ns/op&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;PASS&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ok  &#x9;bench_toon&#x9;5.143s&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;The code is &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/kjk/the-code/tree/master/go/bench_toon&#34;&gt;here&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Benchmarks:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/kjk/the-code/blob/master/go/bench_toon/main_test.go#L29&#34;&gt;BenchmarkToonMarshal&lt;/a&gt; uses &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/toon-format/toon-go&#34;&gt;github.com/toon-format/toon-go&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/kjk/the-code/blob/master/go/bench_toon/main_test.go#L39&#34;&gt;BenchmarkGotoonEncode&lt;/a&gt; uses &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/alpkeskin/gotoon&#34;&gt;github.com/alpkeskin/gotoon&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;What we learned is:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/toon-format/toon-go&#34;&gt;github.com/toon-format/toon-go&lt;/a&gt; is comparable to pretty-printed JSON, which is fair because TOON format is also pretty-printed (and can&amp;rsquo;t be compacted)&lt;/li&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/alpkeskin/gotoon&#34;&gt;github.com/alpkeskin/gotoon&lt;/a&gt; is significantly slower than github.com/toon-format/toon-go&lt;/li&gt;&#xA;&lt;li&gt;JSON compact is way faster than everything else&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;What it means to me is that speed of TOON serialization in Go is not deal breaker. Program would have to spend most of the time serializing for the speed difference to matter.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The readibility of TOON format justifies using it in most cases instead of JSON.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Using &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/toon-format/toon-go&#34;&gt;github.com/toon-format/toon-go&lt;/a&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;github.com/toon-format/toon-go&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Data&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;hello&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;toon&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Marshal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Fatal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;err&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Println&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>From JSON to TOON</title>
   <link href="https://blog.kowalczyk.info/til-from-json-to-toon.html" rel="alternate"></link>
   <updated>2025-12-15T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-12-15:/til-from-json-to-toon.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-from-json-to-toon&#34;&gt;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://toonformat.dev/&#34;&gt;TOON&lt;/a&gt; stands for a Token-Oriented Object Notation.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s a new text format that has the same capability as JSON but uses less space.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It was invented to lower costs of sending data (tokens) to LLM AIs but it has 2 advantages over JSON:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;smaller than JSON&lt;/li&gt;&#xA;&lt;li&gt;more readable than JSON&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;It has implementation in many programming languages, including those I care about: JavaScript and Go.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Therefore it&amp;rsquo;s a good use for non-AI cases e.g.:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;logging structured data&lt;/li&gt;&#xA;&lt;li&gt;sending data from server to client&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;Here&amp;rsquo;s an example of JSON and TOON formats:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;table&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;A&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;currency&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;dolaramerykański&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;code&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;USD&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;rates&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;no&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;001/A/NBP/2024&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;effectiveDate&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2024-01-02&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;mid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.9432&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;no&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;002/A/NBP/2024&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;effectiveDate&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;2024-01-03&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;nt&#34;&gt;&amp;#34;mid&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;3.9909&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;table: A&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;currency: dolaramerykański&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;code: USD&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rates[252]{no,effectiveDate,mid}:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  001/A/NBP/2024,2024-01-02,3.9432&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  002/A/NBP/2024,2024-01-03,3.9909&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;As a result, I&amp;rsquo;m switching to using TOON whenever possible.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Fixing Zed&#39;s debugger keybindings</title>
   <link href="https://blog.kowalczyk.info/til-fixing-zeds-debugger-keybindings.html" rel="alternate"></link>
   <updated>2025-07-22T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-22:/til-fixing-zeds-debugger-keybindings.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-fixing-zeds-debugger-keybindings&#34;&gt;&#xA;&lt;div&gt;Zed has a good debugger built-in but their keybindings are crazy. Thankfully, you can remap them by opening menu &lt;code&gt;Zed&lt;/code&gt; / &lt;code&gt;Settings&lt;/code&gt; / &lt;code&gt;Open key bindings&lt;/code&gt; and adding this to the file:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;use_key_equivalents&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s2&#34;&gt;&amp;#34;bindings&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;f11&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;debugger::StepInto&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;f10&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;debugger::StepOver&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;c1&#34;&gt;// &amp;#34;shift shift&amp;#34;: &amp;#34;file_finder::Toggle&amp;#34;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Those are standard Windows debugging keybindings. &lt;code&gt;F7&lt;/code&gt; and &lt;code&gt;Ctrl + F11&lt;/code&gt; just don&amp;rsquo;t make sense to me.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Ideas for faster web dev cycle</title>
   <link href="https://blog.kowalczyk.info/til-ideas-for-faster-web-dev-cycle.html" rel="alternate"></link>
   <updated>2025-07-22T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-22:/til-ideas-for-faster-web-dev-cycle.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-ideas-for-faster-web-dev-cycle&#34;&gt;&#xA;&lt;div&gt;I strongly believe that fast iteration cycle is important for productivity. In programming fast iteration means: how quickly can I go from finishing writing the code to testing it. That&amp;rsquo;s why I don&amp;rsquo;t like languages that compile slowly: slow compilation puts a hard limit on your iteration cycle.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That&amp;rsquo;s a general principle. How does it translate to actions?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;m glad you asked.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;simulated-errors&#34;&gt;&lt;div&gt;Simulated errors&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#simulated-errors&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;m writing a web app and some code paths might fail e.g. server returns an error response.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;When that happens I want to display an error message to the user. I want to test that but server doesn&amp;rsquo;t typically return errors.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I can modify the server to return error and restart it but in a compiled language like Go it&amp;rsquo;s a whole thing.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Instead I can force error condition in the code. Because web dev typically offers hot reload of code, I can modify the code to pretend the request failed, save the code, reload the app and I&amp;rsquo;m testing the error handling.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To make it less ad-hoc another strategy is to have debug flags on window object e.g.:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;simulateError&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Then the code will have:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;try&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;simulateError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;throw&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;fetch failed&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(...);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;That way I can toggle &lt;code&gt;window.debug.simulateError&lt;/code&gt; in dev tools console, without changing the code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I have to repeat this code for every &lt;code&gt;fetch()&lt;/code&gt;. More principled approach is:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;myFetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uri&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;opts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;simulateError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;throw&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Error&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;featch failed&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uri&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;opts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;To go even further, we could simulate different kinds of network errors:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Response.ok is false&lt;/li&gt;&#xA;&lt;li&gt;response is 404 or 500&lt;/li&gt;&#xA;&lt;li&gt;failed to reach the server&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;We can change &lt;code&gt;simulateError&lt;/code&gt; from bool to a number and have:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;myFetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uri&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;opts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;se&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;window&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;debug&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;simulateError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;se&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// simulate Response.ok is false&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;se&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// simulate 404 response&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;se&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;===&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// simulate network offline&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uri&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;opts&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#x9;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;start-by-show-dialog&#34;&gt;&lt;div&gt;Start by show dialog&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#start-by-show-dialog&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Let&amp;rsquo;s say I&amp;rsquo;m working on a new dialog e.g. rename dialog. To get to that dialog I have to perform some UI action e.g. use context menu and click the &lt;code&gt;Rename note&lt;/code&gt; menu item.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Not a big deal but I&amp;rsquo;m still working on the dialog so it&amp;rsquo;s a bit annoying to repeat that UI action every time I move the button to the right, to see how it&amp;rsquo;ll look.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In Svelte we do:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;showingRenameDialog&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;$state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;showRenameDialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;showingRenameDialog&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;showingRenameDialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;RenameDialog&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/RenameDialog&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;To speed up dev cycle:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;showingRenameDialog&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;$state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// show while we&amp;#39;re working ont&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;While I&amp;rsquo;m still designing and writing code for the dialog, show it by default. That way app reloads due to changing code won&amp;rsquo;t require you to manually redo UI actions to trigger the dialog.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;ad-hoc-test-code&#34;&gt;&lt;div&gt;Ad-hoc test code&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#ad-hoc-test-code&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Let&amp;rsquo;s say you&amp;rsquo;re writing a non-trivial code server code to process a request. Let&amp;rsquo;s say the request is a POST with body containing zip file with images which the server needs to unzip, resize the files, save them to a file system.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You want to test it as you implement the logic but iteration cycle is slow:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;you write the code&lt;/li&gt;&#xA;&lt;li&gt;recompile and restart the server&lt;/li&gt;&#xA;&lt;li&gt;go through UI actions to send the request&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;Most of the code (unpacking zip file, resizing images) can be tested without doing the request. So you isolate the function:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;resizeImagesInZip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;zipData&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;byte&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;error&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// the code you&amp;#39;re writing on&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Now you have to trigger it easily. The simplest way is ad-hoc test code:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;zipData&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;loadTestZipFileMust&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;resizeImagesInZip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;zipData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;While you&amp;rsquo;re working on the code, the server just runs the test code. When you&amp;rsquo;re done, you switch it off:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// leave the code so that you can re-enable it&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// easily in the future&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;zipData&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;loadTestZipFileMust&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;resizeImagesInZip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;zipData&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Those are few tactical tips to increase dev cycles.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You can come up with more such ideas by asking yourself: how can I speed iteration cycle?&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Zed debug setup for go server / Svelte web app</title>
   <link href="https://blog.kowalczyk.info/til-zed-debug-setup-for-go-server-svelte-web-app.html" rel="alternate"></link>
   <updated>2025-07-21T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-21:/til-zed-debug-setup-for-go-server-svelte-web-app.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-zed-debug-setup-for-go-server-svelte-web-app&#34;&gt;&#xA;&lt;div&gt;Today I figured out how to setup &lt;a target=&#34;_blank&#34; href=&#34;https://zed.dev/&#34;&gt;Zed&lt;/a&gt; to debug, at the same time, my go server and Svelte web app.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;My dev setup for working on my web app is:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;go server is run with &lt;code&gt;-run-dev&lt;/code&gt; arg&lt;/li&gt;&#xA;&lt;li&gt;go server provides backend apis and proxies requests it doesn&amp;rsquo;t handle to a vite dev server that does the serving of JavaScript etc. files from my Svelte code&lt;/li&gt;&#xA;&lt;li&gt;go server in &lt;code&gt;-run-dev&lt;/code&gt; mode automatically launches &lt;code&gt;vite dev&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;go server runs on port 9339&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s possible to setup Zed to debug both server and frontend JavaScript code. In retrospect it&amp;rsquo;s simple, but took me a moment to figure out.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I needed to create the following &lt;code&gt;.zed/debug.json&lt;/code&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// Project-local debug tasks&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// For more documentation on how to configure debug tasks,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;// see: https://zed.dev/docs/debugger&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;adapter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Delve&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;run go server&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;request&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;launch&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;mode&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;debug&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;program&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;cwd&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;${ZED_WORKTREE_ROOT}&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;-run-dev&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;-no-open&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;buildFlags&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;env&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;adapter&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;JavaScript&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;label&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Debug in Chrome&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;chrome&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;request&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;launch&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:9339/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;webRoot&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;$ZED_WORKTREE_ROOT/src&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;console&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;integratedTerminal&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;skipFiles&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;lt;node_internals&amp;gt;/**&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;It&amp;rsquo;s mostly self-exploratory.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;First entry tells Zed to build go program with &lt;code&gt;go build .&lt;/code&gt; and run the resulting executable under the debugger with &lt;code&gt;-run-dev -no-open&lt;/code&gt; args.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Second entry tells to launch Chrome in debug mode with &lt;code&gt;http://localhost:9339/&lt;/code&gt; and that files seen by Chrome come from &lt;code&gt;src/&lt;/code&gt; directory i.e. if browser loads &lt;code&gt;/foo.js&lt;/code&gt; the source file is &lt;code&gt;src/foo.js&lt;/code&gt;. This is necessary to be able to set breakpoints in Zed and have them propagate to Chrome.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This eliminates the need for terminal so I can edit and debug with just Zed and Chrome.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This is a great setup. I&amp;rsquo;m impressed with &lt;a target=&#34;_blank&#34; href=&#34;https://zed.dev/&#34;&gt;Zed&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Stage manager in Mac OS</title>
   <link href="https://blog.kowalczyk.info/til-stage-manager-in-mac-os.html" rel="alternate"></link>
   <updated>2025-07-21T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-21:/til-stage-manager-in-mac-os.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-stage-manager-in-mac-os&#34;&gt;&#xA;&lt;div&gt;Stage Manager in Mac OS is not a secret, but I&amp;rsquo;ve only learned about it recently.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s off by default so you have to enable it in system settings:&#xA; &lt;img class=&#34;blog-img&#34; src=&#34;/md/mac_state_manager.png&#34; alt=&#34;&#34; /&gt;&#xA;It&amp;rsquo;s hard to describe in words, so you&amp;rsquo;ll have to try it. And experiment a bit because I didn&amp;rsquo;t get in the first hour.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s a certain way to manage windows for less clutter. Imagine you have a browser, an editor and a terminal i.e. 3 windows. Might be annoying to have them all shown on screen.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;When Stage Manager is enabled, thumbnails of windows are on the left edge of the screen and you can switch to the window by clicking the thumbnail.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;By default Stage Manager shows each window by itself on screen. You can group them by dragging thumbnail onto screen. For example, when I&amp;rsquo;m developing, I&amp;rsquo;m using text editor and terminal so I will group them so they are both visible on screen at the same time, but not the other apps.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;So far I&amp;rsquo;m enjoying using Stage Manager.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>AltTab for Mac OS</title>
   <link href="https://blog.kowalczyk.info/til-alttab-for-mac-os.html" rel="alternate"></link>
   <updated>2025-07-21T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-21:/til-alttab-for-mac-os.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-alttab-for-mac-os&#34;&gt;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://alt-tab-macos.netlify.app/&#34;&gt;AltTab&lt;/a&gt; solves a simple problem really well: it brings Windows-style &lt;code&gt;Alt + Tab&lt;/code&gt; window switching to Mac OS.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That&amp;rsquo;s it. That&amp;rsquo;s all there is to it.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I think Windows way of Alt - tabbing windows is better than Mac&amp;rsquo;s.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s a must for someone like me, who switches between using Windows and Mac OS. That small difference drove me mad when using Mac so super thankful someone wrote an app that fixes it.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s free and open source so no excuse to not to use it.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>lazy import of JavaScript modules</title>
   <link href="https://blog.kowalczyk.info/til-lazy-import-of-javascript-modules.html" rel="alternate"></link>
   <updated>2025-07-20T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-20:/til-lazy-import-of-javascript-modules.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-lazy-import-of-javascript-modules&#34;&gt;&#xA;&lt;div&gt;When working on big JavaScript web apps, you can &lt;a href=&#34;/til-vite-rollup-manualchunks.html&#34;&gt;split the bundle in multiple chunks&lt;/a&gt; and import selected chunks lazily, only when needed. That makes the main bundle smaller, faster to load and parse.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;How to lazy import a module?&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hljs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;highlight.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;).&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;is equivalent of:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hljs&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;highlight.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Now:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;libZip&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;@zip.js/zip.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;blobReader&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;libZip&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;BlobReader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;blob&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Is equivalent to:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;BlobReader&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;@zip.js/zip.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;It&amp;rsquo;s simple if we call it from &lt;code&gt;async&lt;/code&gt; function but sometimes we want to lazy load from non-async function so things might get more complicated:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;isLazyImportng&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hljs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;markdownIt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;markdownItAnchor&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;lazyImports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;isLazyImportng&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;isLazyImportng&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;promises&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;Promise&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;all&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;([&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;highlight.js&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;markdown-it&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;markdown-it-anchor&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;]);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;hljs&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;promises&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;markdownIt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;promises&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;markdownItAnchor&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;promises&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;].&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;We can run it from non-async function:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;doit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nx&#34;&gt;lazyImports&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;().&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;then&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;hljs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;c1&#34;&gt;// use hljs to do something&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;I&amp;rsquo;ve included protection against kicking of lazy import more than once. That means on second and n-th call we might not yet have the module loaded so &lt;code&gt;hljs&lt;/code&gt; will be still &lt;code&gt;undefined&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Using await in Svelte 5 components</title>
   <link href="https://blog.kowalczyk.info/til-using-await-in-svelte-5-components.html" rel="alternate"></link>
   <updated>2025-07-20T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-20:/til-using-await-in-svelte-5-components.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-using-await-in-svelte-5-components&#34;&gt;&#xA;&lt;div&gt;Svelte 5 just added a way to use async function in components. This is from &lt;a target=&#34;_blank&#34; href=&#34;https://www.youtube.com/watch?v=e-1pVKUWlOQ&#34;&gt;Rich Harris talk&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;the-simplest-component&#34;&gt;&lt;div&gt;The simplest component&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#the-simplest-component&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;async&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;multiply&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;uri&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;sb&#34;&gt;`/multiply?x=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;x&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;&amp;amp;y=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;y&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;rsp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;uri&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;rsp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;text&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;parseInt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;resp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;$state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;{n} * 2 = {await multiply(n, 2)}&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Previously you couldn&amp;rsquo;t do &lt;code&gt;{await multiply(n, 2)&lt;/code&gt; because Svelte didn&amp;rsquo;t understand promises. Now you can.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;aborting-outdated-requests&#34;&gt;&lt;div&gt;Aborting outdated requests&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#aborting-outdated-requests&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Imagine getting search results from a server based on what you type in an input box.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If you type &lt;code&gt;foo&lt;/code&gt;, we first send request for &lt;code&gt;f&lt;/code&gt;, then for &lt;code&gt;fo&lt;/code&gt; then for &lt;code&gt;foo&lt;/code&gt; at which point we don&amp;rsquo;t care about the results for &lt;code&gt;f&lt;/code&gt; and &lt;code&gt;fo&lt;/code&gt;. Svelte 5 can handle aborting outdated requests:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;getAbortSignal&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;svelte&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;search&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;$state&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;API&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://dummyjson.com/product/search&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;response&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;$derived&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;API&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;?q=&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;search&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;sb&#34;&gt;`&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nx&#34;&gt;signal&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;getAbortSignal&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;input&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;bind:value&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;{search}&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;svelte:boundary&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;{#each (await response.json().products as product)}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;li&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;{product.title}&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;li&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;{/each}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;ul&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>vite /rollup manualChunks</title>
   <link href="https://blog.kowalczyk.info/til-vite-rollup-manualchunks.html" rel="alternate"></link>
   <updated>2025-07-19T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-19:/til-vite-rollup-manualchunks.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-vite-rollup-manualchunks&#34;&gt;&#xA;&lt;div&gt;In MS-DOS days programmers were limited to 640 kB of code. When their programs became bigger than that they had to implement tricky code to load / unload code chunks on demand.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In web apps we&amp;rsquo;re not limited by size but it&amp;rsquo;s still a good idea to strive for the smallest possible JavaScript bundle. We can do it by extracting rarely used pieces of functionality into separate JavaScript chunks and import them lazily. This makes the app faster to load, faster to parse and run.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For example, in &lt;a target=&#34;_blank&#34; href=&#34;https://edna.arslexis.io&#34;&gt;Edna&lt;/a&gt; I use &lt;code&gt;markdown-it&lt;/code&gt; and &lt;code&gt;highlight.js&lt;/code&gt; library only in a certain scenario. By putting it in it&amp;rsquo;s separate chunk, I save almost 1 MB of uncompressed JavaScript in main bundle. Faster to download, faster to run.&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;../dist/assets/markdownit-hljs-DbctGXX9.js          1,087.33 kB │ gzip: 358.42 kB&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;To split in chunks you configure &lt;code&gt;rollup&lt;/code&gt; in &lt;code&gt;vite.config.js&lt;/code&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;manualChunks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;c1&#34;&gt;// partition files into chunks&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;default&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;defineConfig&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;nx&#34;&gt;build&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;nx&#34;&gt;rollupOptions&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;nx&#34;&gt;output&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&#x9;&lt;span class=&#34;nx&#34;&gt;manualChunks&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;manualChunks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;code&gt;manualChunks()&lt;/code&gt; functions takes a path of the file (don&amp;rsquo;t know why everyone calls it an &lt;code&gt;id&lt;/code&gt;). If you return a string for a given path, you tell rollup to bundle that file in a given chunk. If you return nothing (i.e. &lt;code&gt;undefined&lt;/code&gt;) rollup will decide on how to chunk automatically, most likely putting everything into a single chunk&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It gets called for &lt;code&gt;.css&lt;/code&gt; files, &lt;code&gt;.js&lt;/code&gt; files and probably others.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Here&amp;rsquo;s my hard won wisdom:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;console.log(id)&lt;/code&gt; when working on &lt;code&gt;manualChunks()&lt;/code&gt; to see what files are processed&lt;/li&gt;&#xA;&lt;li&gt;chunk specific modules from &lt;code&gt;node_modules&lt;/code&gt; to be lazy loaded&lt;/li&gt;&#xA;&lt;li&gt;everything else from &lt;code&gt;node_modules&lt;/code&gt; goes into &lt;code&gt;vendor&lt;/code&gt; chunk&lt;/li&gt;&#xA;&lt;li&gt;the rest is my own code and goes into lmain chunk as decided by rollup&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;Seems simple enough:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;manualChunks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;console&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;log&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;const&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;chunksDef&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/@zip.js/zip.js/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;zipjs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/prettier/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;prettier&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// markdown-it and highlight.js are used together in askai.svelte&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;/markdown-it/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;/markdown-it-anchor/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;/highlight.js/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;  &lt;span class=&#34;s2&#34;&gt;&amp;#34;/entities/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;/linkify-it/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;/mdurl/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;/punycode.js/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;/uc.micro/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s2&#34;&gt;&amp;#34;markdownit-hljs&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;],&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;of&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;chunksDef&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;length&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;++&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;includes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;def&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;n&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;];&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// bundle all other 3rd-party modules into a single vendor.js module&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;includes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/node_modules/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;vendor&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// when we return undefined, rollup will decide&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;This is real example from Edna. I&amp;rsquo;ve put &lt;code&gt;zip.js&lt;/code&gt;, &lt;code&gt;prettier&lt;/code&gt; and &lt;code&gt;markdown-it&lt;/code&gt; + &lt;code&gt;markdown-it-anchor&lt;/code&gt; + &lt;code&gt;highlight.js&lt;/code&gt; into their own chunks, which I lazily import.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Things to note:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;order is important. If I match &lt;code&gt;/node_modules/&lt;/code&gt; first, then everything would end up in &lt;code&gt;vendor&lt;/code&gt; bundle&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;id&lt;/code&gt; is a full path of bundled file in Unix format e.g. &lt;code&gt;C:/Users/kjk/src/elaris/node_modules/prettier/standalone.mjs&lt;/code&gt;. People seem to match the path against just package name like &lt;code&gt;prettier&lt;/code&gt;. I match against &lt;code&gt;/prettier/&lt;/code&gt; so that if some file has string &lt;code&gt;prettier&lt;/code&gt; in it, it won&amp;rsquo;t be accidentally put in &lt;code&gt;prettier&lt;/code&gt; chunk&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;/entities/&lt;/code&gt;, &lt;code&gt;/mdurl/&lt;/code&gt; etc. are used by &lt;code&gt;markdown-it&lt;/code&gt; so they should be included in its chunk. That&amp;rsquo;s where &lt;code&gt;console.log(id)&lt;/code&gt; is helpful. I saw modules that I didn&amp;rsquo;t explicitly put in &lt;code&gt;package.json&lt;/code&gt; which means they are implicit dependencies. I used  &lt;code&gt;bun.lock&lt;/code&gt; to see which package depends on those mysterious packages and that&amp;rsquo;s how I found what is used by &lt;code&gt;markdown-it&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;There were 2 remaining problems.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I also had this in my code:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;highlight.js/styles/github.css&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;code&gt;manualChunks&lt;/code&gt; was called for &lt;code&gt;&amp;quot;highlight.js/styles/github.css&amp;quot;&lt;/code&gt; to which I returned &lt;code&gt;markdownit-hljs&lt;/code&gt; so it was put in its own chunk. Which was too much because I didn&amp;rsquo;t want to lazy import a small CSS file, so I told rollup to put all &lt;code&gt;.css&lt;/code&gt; files in main CSS chunk:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;manualChunks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// pack all .css files in the same chunk&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;endsWith&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;.css&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;c1&#34;&gt;// ... rest of the code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;There was one more thing that was a big pain in the ass to debug.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To verify things are properly chunked I opened Dev Tools in Chrome and looked at network tab. To my surprise, &lt;code&gt;markdownit-hljs&lt;/code&gt; was loaded immediately.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;After lots of debugging and research: turns out that vite bundles some helper functions. Because I didn&amp;rsquo;t specify explicitly which chunk they should go into, rollup decided to put them in &lt;code&gt;markdownit-hljs&lt;/code&gt; chunk. Because main chunk was using that function, it had to import it, defeating my cunning plan to load it lazily later.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The fix was to direct those known helper function into &lt;code&gt;vendor&lt;/code&gt; bundle:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;function&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;manualChunks&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;c1&#34;&gt;// ... other code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;c1&#34;&gt;// bundle all other 3rd-party modules into a single vendor.js module&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;includes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;/node_modules/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;||&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;nx&#34;&gt;ROLLUP_COMMON_MODULES&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;some&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;((&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;commonModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;includes&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;commonModule&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;vendor&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;c1&#34;&gt;// ... rest of the code&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;You can read more at:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/vitejs/vite/issues/17823&#34;&gt;https://github.com/vitejs/vite/issues/17823&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/vitejs/vite/issues/19758&#34;&gt;https://github.com/vitejs/vite/issues/19758&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/vitejs/vite/issues/5189&#34;&gt;https://github.com/vitejs/vite/issues/5189&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;Things might still go wrong. I got one invalid build that created a chunk that wouldn&amp;rsquo;t parse in the browser.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For that reason I suggest to start simple: empty &lt;code&gt;manualChunks()&lt;/code&gt; function that packs everything in one chunk. Then add desired chunks one by one and after each change.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;And how to lazy import things?&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;markdownIt&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kr&#34;&gt;await&lt;/span&gt; &lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;markdown-it&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)).&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;is equivalent to static import:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kr&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;markdownIt&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;from&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;markdown-it&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Read more about &lt;a href=&#34;/til-lazy-import-of-javascript-modules.html&#34;&gt;lazy imports&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Increase software sales by 50% or more</title>
   <link href="https://blog.kowalczyk.info/a-tm7o/increase-software-sales-by-50-or-more.html" rel="alternate"></link>
   <updated>2025-07-18T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-18:/a-tm7o/increase-software-sales-by-50-or-more.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;tm7o&#34;&gt;&#xA;&lt;div&gt;This is re-post of&#xA;&lt;a target=&#34;_blank&#34; href=&#34;http://web.archive.org/web/20061027060058/http://www.dexterity.com/articles/registration-incentives.htm&#34;&gt;How to Permanently Increase Your Sales by 50% or More in Only One Day&lt;/a&gt; article by Steve Pavlina&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Of all the things you can do to increase your sales, one of the highest leverage activities is attempting to increase your products&amp;rsquo; registration rate. Increasing your registration rate from 1.0% to 1.5% means that you simply convince one more downloader out of every 200 to make the decision to buy. Yet that same tiny increase will literally increase your sales by a full 50%. If you&amp;rsquo;re one of those developers who simply slapped the ubiquitous 30-day trial incentive on your shareware products without going any further than that, then I think a 50% increase in your registration rate is a very attainable goal you can achieve if you spend just one full day of concentrated effort on improving your product&amp;rsquo;s ability to sell. My hope is that this article will get you off to a good start and get you thinking more creatively. And even if you fail, your result might be that you achieve only a 25% or a 10% increase. How much additional money would that represent to you over the next five years of sales?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;What influence, if any, did the title of this article have on your decision to read it? If I had titled this article, &amp;ldquo;Registration Incentives,&amp;rdquo; would you have been more or less likely to read it now? Note that the title expresses a specific and clear benefit to you. It tells you exactly what you can expect to gain by reading it. Effective registration incentives work the same way. They offer clear, specific benefits to the user if a purchase is made.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In order to improve your registration incentives, the first thing you need to do is to adopt some new beliefs that will change your perspective. I&amp;rsquo;m going to introduce you to what I call the &amp;ldquo;lies of success&amp;rdquo; in the shareware industry. These are statements that are not true at all, but if you accept them as true anyway, you&amp;rsquo;ll achieve far better results than if you don&amp;rsquo;t.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;rule-1-what-you-are-selling-is-merely-the-difference-between-the-shareware-and-the-registered-versions-not-the-registered-version-itself&#34;&gt;&lt;div&gt;Rule 1: What you are selling is merely the difference between the shareware and the registered versions, not the registered version itself.&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#rule-1-what-you-are-selling-is-merely-the-difference-between-the-shareware-and-the-registered-versions-not-the-registered-version-itself&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Note that this is not a true statement, but if you accept it as true, you&amp;rsquo;ll immediately begin to see the weaknesses in your registration incentives. If there are few additional benefits for buying the full version vs. using the shareware version, then you aren&amp;rsquo;t offering the user strong enough incentives to make the full purchase.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;rule-2-the-sole-purpose-of-the-shareware-version-is-to-close-the-sale&#34;&gt;&lt;div&gt;Rule 2: The sole purpose of the shareware version is to close the sale.&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#rule-2-the-sole-purpose-of-the-shareware-version-is-to-close-the-sale&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;This is our second lie of success. Note the emphasis on the word &amp;ldquo;close.&amp;rdquo; Your shareware version needs to act as a direct sales vehicle. It must be able to take the user all the way to the point of purchase, i.e. your online order form, ideally with nothing more than a few mouse clicks. Anything that detracts from achieving a quick sale is likely to hurt sales.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;rule-3-the-customer-s-perspective-is-the-only-one-that-matters&#34;&gt;&lt;div&gt;Rule 3: The customer&amp;rsquo;s perspective is the only one that matters.&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#rule-3-the-customer-s-perspective-is-the-only-one-that-matters&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Defy this rule at your peril. Customers don&amp;rsquo;t care that you spent 2000 hours creating your product. Customers don&amp;rsquo;t care that you deserve the money for your hard work. Customers don&amp;rsquo;t care that you need to do certain things to prevent piracy. All that matters to them are their own personal wants and needs. Yes, these are lies of success. Some customers will care, but if you design your registration incentives assuming they only care about their own self-interests, your motivation to buy will be much stronger than if you merely appeal to their sense of honesty, loyalty, or honor. Assume your customers are all asking, &amp;ldquo;What&amp;rsquo;s in it for me if I choose to buy? What will I get? How will this help me?&amp;rdquo; I don&amp;rsquo;t care if you&amp;rsquo;re selling to Fortune 500 companies. At some point there will be an individual responsible for causing the purchase to happen, and that individual is going to consider how the purchase will affect him/her personally: &amp;ldquo;Will this purchase get me fired? Will it make me look good in front of my peers? Will this make my job easier or harder?&amp;rdquo;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Many shareware developers get caught in the trap of discriminating between honest and dishonest users, believing that honest users will register and dishonest ones won&amp;rsquo;t. This line of thinking will ultimately get you nowhere, and it violates the third lie of success. When you make a purchase decision, how often do you use honesty as the deciding factor? Do you ever say, &amp;ldquo;I will buy this because I&amp;rsquo;m honest?&amp;rdquo; Or do you consider other more selfish factors first, such as how it will make you feel to purchase the software? The truth is that every user believes s/he is honest, so no user applies the honesty criterion when making a purchase decision. Thinking of your users in terms of honest ones vs. dishonest ones is a complete waste of time because that&amp;rsquo;s not how users primarily view themselves.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;rule-4-customers-buy-on-emotion-and-justify-with-fact&#34;&gt;&lt;div&gt;Rule 4: Customers buy on emotion and justify with fact.&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#rule-4-customers-buy-on-emotion-and-justify-with-fact&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;If you&amp;rsquo;re honest with yourself, you&amp;rsquo;ll see that this is how you make most purchase decisions. Remember the last time you bought a computer. Is it fair to say that you first became emotionally attached to the idea of owning a new machine? For me, it&amp;rsquo;s the feeling of working faster, owning the latest technology, and being more productive that motivates me to go computer shopping. Once I&amp;rsquo;ve become emotionally committed, the justifications follow: &amp;ldquo;It&amp;rsquo;s been two years since I&amp;rsquo;ve upgraded, it will pay for itself with the productivity boost I gain, I can easily afford it, I&amp;rsquo;ve worked hard and I deserve a new machine, etc.&amp;rdquo; You use facts to justify the purchase. Once you understand how purchase decisions are made, you can see that your shareware products need to first get the user emotionally invested in the purchase, and then you give them all the facts they need to justify it.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Now that we&amp;rsquo;ve gotten these four lies of success out of the way, let&amp;rsquo;s see how we might apply them to create some compelling registration incentives. Let&amp;rsquo;s start with Rule 1. What incentives can be spawned from this rule? The common 30-day trial is one obvious derivative. If you are only selling the difference between the shareware and registered versions, then a 30-day trial implies that you are selling unlimited future days of usage of the program after the trial period expires. This is a powerful incentive, and it&amp;rsquo;s been proven effective for products that users will continue to use month after month. 30-day trials are easy for users to understand, and they&amp;rsquo;re also easy to implement. You could also experiment with other time periods such as 10 days, 14 days, or 90 days. The only way of truly knowing which will work best for your products is to experiment.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;But let&amp;rsquo;s see if we can move a bit beyond the basic 30-day trial here by mixing in a little of Rule 3. How would the customer perceive a 30-day trial? In most cases 30 days is plenty of time to evaluate a product. But in what situations would a 30-day trial have a negative effect? A good example is when the user downloads, installs, and briefly checks out a product s/he may not have time to evaluate right away. By the time the user gets around to fully evaluating it, the shareware version has already expired, and a sale may be lost as a result. To get around this limitation, many shareware developers have started offering 30 days of actual program usage instead of 30 consecutive days. This allows the user plenty of time to try out the program at his/her convenience. Another possibility would be to limit the number of times the program can be run. The basic idea is that you are giving away limited usage and selling unlimited usage of the program. This incentive definitely works if your product is one that will be used frequently over a long period of time (much longer than the trial period).&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The flip side of usage limitation is to offer an additional bonus for buying within a certain period of time. For instance, in my game Dweep, I offer an extra 5 free bonus levels to everyone who buys within the first 10 days. In truth I give the bonus levels to everyone who buys, but the incentive is real from the customer&amp;rsquo;s point of view. Remember Rule 3 - it doesn&amp;rsquo;t matter what happens on my end; it only matters what the customer perceives. Any customer that buys after the first 10 days will be delighted anyway to receive a bonus they thought they missed.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;So if your product has no time-based incentives at all, this is the first place to start. When would you pay your bills if they were never due, and no interest was charged on late payments? Use time pressure to your advantage, either by disabling features in the shareware version after a certain time or by offering additional bonuses for buying sooner rather than later. If nothing else and if it&amp;rsquo;s legal in your area, offer a free entry in a random monthly drawing for a small prize, such as one of your other products, for anyone who buys within the first X days.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Another logical derivative of Rule 1 is the concept of feature limitation. On the crippling side, you can start with the registered version and begin disabling functionality to create the shareware version. Disabling printing in a shareware text editor is a common strategy. So is corrupting your program&amp;rsquo;s output with a simple watermark. For instance, your shareware editor could print every page with your logo in the background. Years ago the Association of Shareware Professionals had a strict policy against crippling, but that policy was abandoned, and crippling has been recognized as an effective registration incentive.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It is certainly possible to apply feature limitation without having it perceived as crippling. This is especially easy for games, which commonly offer a limited number of playable levels in the shareware version with many more levels available only in the registered version. In this situation you offer the user a seemingly complete experience of your product in the shareware version, and you provide additional features on top of that for the registered version.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Time-based incentives and feature-based incentives are perhaps the two most common strategies used by shareware developers for enticing users to buy. Which will work best for you? You will probably see the best results if you use both at the same time. Imagine you&amp;rsquo;re the end user for a moment. Would you be more likely to buy if you were promised additional features and given a deadline to make the decision? I&amp;rsquo;ve seen several developers who were using only one of these two strategies increase their registration rates dramatically by applying the second strategy on top of the first. If you only use time-based limitations, how could you apply feature limitation as well? Giving the user more reasons to buy will translate to more sales per download.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;One you have both time-based and feature-based incentives to buy, the next step is to address the user&amp;rsquo;s perceived risk by applying a risk-reversal strategy. Fortunately, the shareware model already reduces the perceived risk of purchasing significantly, since the user is able to try before buying. But let&amp;rsquo;s go a little further, keeping Rule 3 in mind. What else might be a perceived risk to the user? What if the user reaches the end of the trial period and still isn&amp;rsquo;t certain the product will do what s/he needs? What if the additional features in the registered version don&amp;rsquo;t work as the user expects? What can we do to make the decision to purchase safer for the user?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;One approach is to offer a money-back guarantee. I&amp;rsquo;ve been offering a 60-day unconditional money-back guarantee on all my products since January 2000. If someone asks for their money back for any reason, I give them a full refund right away. So what is my return rate? Well, it&amp;rsquo;s about 8%. Just kidding! Would it surprise you to learn that my return rate at the time of this writing is less than 0.2%? Could you handle two returns out of every 1000 sales? My best estimate is that this one technique increased my sales by 5-10%, and it only took a few minutes to implement. When I suggest this strategy to other shareware developers, the usual reaction is fear. &amp;ldquo;But everyone would rip me off,&amp;rdquo; is a common response. I suggest trying it for yourself on an experimental basis; a few brave souls have already tried it and are now offering money-back guarantees prominently. Try putting it up on your web site for a while just to convince yourself it works. You can take it down at any time. After a few months, if you&amp;rsquo;re happy with the results, add the guarantee to your shareware products as well. I haven&amp;rsquo;t heard of one bad outcome yet from those who&amp;rsquo;ve tried it.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If you use feature limitation in your shareware products, another important component of risk reversal is to show the user exactly what s/he will get in the full version. In Dweep I give away the first five levels in the demo version, and purchasing the full version gets you 147 more levels. When I thought about this from the customer&amp;rsquo;s perspective (Rule 3), I realized that a perceived risk is that s/he doesn&amp;rsquo;t know if the registered version levels will be as fun as the demo levels. So I released a new demo where you can see every level but only play the first five. This lets the customer see all the fun that awaits them. So if you have a feature-limited product, show the customer how the feature will work. For instance, if your shareware version has printing disabled, the customer could be worried that the full version&amp;rsquo;s print capability won&amp;rsquo;t work with his/her printer or that the output quality will be poor. A better strategy is to allow printing, but to watermark the output. This way the customer can still test and verify the feature, and it doesn&amp;rsquo;t take much imagination to realize what the output will look like without the watermark.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Our next step is to consider Rule 2 and include the ability close the sale. It is imperative that you include an &amp;ldquo;instant gratification&amp;rdquo; button in your shareware products, so the customer can click to launch their default web browser and go directly to your online order form.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If you already have a &amp;ldquo;buy now&amp;rdquo; button in your products, go a step further. A small group of us have been finding that the more liberally these buttons are used, the better. If you only have one or two of these buttons in your shareware program, you should increase the count by at least an order of magnitude. The current Dweep demo now has over 100 of these buttons scattered throughout the menus and dialogs. This makes it extremely easy for the customer to buy, since s/he never has to hunt around for the ordering link.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;What should you label these buttons? &amp;ldquo;Buy now&amp;rdquo; or &amp;ldquo;Register now&amp;rdquo; are popular, so feel free to use one of those. I took a slightly different approach by trying to think like a customer (Rule 3 again). As a customer the word &amp;ldquo;buy&amp;rdquo; has a slightly negative association for me. It makes me think of parting with my cash, and it brings up feelings of sacrifice and pressure. The words &amp;ldquo;buy now&amp;rdquo; imply that I have to give away something. So instead, I use the words, &amp;ldquo;Get now.&amp;rdquo; As a customer I feel much better about getting something than buying something, since &amp;ldquo;getting&amp;rdquo; brings up only positive associations. This is the psychology I use, but at present, I don&amp;rsquo;t know of any hard data showing which is better. Unless you have a strong preference, trust your intuition.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Make it as easy as possible for the willing customer to buy. The more methods of payment you accept, the better your sales will be. Allow the customer to click a button to print an order form directly from your program and mail it with a check or money order. On your web order form, include a link to a printable text order form for those who are afraid to use their credit cards online. If you only accept two or three major credit cards, sign up with a registration service to handle orders for those you don&amp;rsquo;t accept.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;So far we&amp;rsquo;ve given the customer some good incentives to buy, minimized perceived risk, and made it easy to make the purchase. But we haven&amp;rsquo;t yet gotten the customer emotionally invested in making the purchase decision. That&amp;rsquo;s where Rule 4 comes in. First, we must recognize the difference between benefits and features. We need to sell the sizzle, not the steak. Features describe your product, while benefits describe what the user will get by using your product. For instance, a personal information manager (PIM) program may have features such as daily, weekly, and monthly views; task and event timers; and a contact database. However, the benefits of the program might be that it helps the user be more organized, earn more money, and enjoy more free time. For a game, the main benefit might be fun. For a nature screensaver, it could be relaxation, beauty appreciation, or peace. Features are logical; benefits are emotional. Logical features are an important part of the sale, but only after we&amp;rsquo;ve engaged the customer&amp;rsquo;s emotions.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Many products do a fair job of getting the customer emotionally invested during the trial period. If you have an addictive program or one that&amp;rsquo;s fun to use, such as a game, you may have an easy time getting the customer emotionally attached to using it because the experience is already emotional in nature. But whatever your product is, you can increase your sales by clearly illustrating the benefits of making the purchase. A good place to do this is in your nag screens. I use nag screens both before and after the program runs to remind the user of the benefits of buying the full version. At the very least, include a nag screen when the customer exits the program, so the last thing s/he sees will be a reminder of the product&amp;rsquo;s benefits. Take this opportunity to sell the user on the product. Don&amp;rsquo;t expect features like &amp;ldquo;customizable colors&amp;rdquo; to motivate anyone to buy. Paint a picture of what benefits the user will obtain with the full version. Will I save time? Will I have more fun? Will I live longer, save money, or feel better? The simple change from feature-oriented selling to benefit-oriented selling can easily double or triple your sales. Be sure to use this approach on your web site as well if you don&amp;rsquo;t already. Developers who&amp;rsquo;ve recently made the switch have been reporting some amazing results.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If you&amp;rsquo;re drawing a blank when trying to come up with benefits for your products, the best thing you can do is to email some of your old customers and ask them why they bought your program. What did it do for them? I&amp;rsquo;ve done this and was amazed at the answers I got back. People were buying my games for reasons I&amp;rsquo;d never anticipated, and that told me which benefits I needed to emphasize in my sales pitch.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The next key is to make your offer irresistible to potential customers. Find ways to offer the customer so much value that it would be harder to say no than to say yes. Take a look at your shareware product as if you were a potential customer who&amp;rsquo;d never seen it before. Being totally honest with yourself, would you buy this program if someone else had written it? If not, don&amp;rsquo;t stop here. As a potential customer, what additional benefits or features would put you over the top and convince you to buy? More is always better than less. In the original version of Dweep, I offered ten levels in the demo and thirty in the registered version. Now I offer only five demo levels and 152 in the full version, plus a built-in level editor. Originally, I offered the player twice the value of the demo; now I&amp;rsquo;m offering over thirty times the value. I also offer free hints and solutions to every level; the benefit here is that it minimizes player frustration. As I keep adding bonuses for purchasing, the offer becomes harder and harder to resist.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;What clever bonuses can you throw in for registering? Take the time to watch an infomercial. Notice that there is always at least one &amp;ldquo;FREE&amp;rdquo; bonus thrown in. Consider offering a few extra filters for an image editor, ten extra images for a screensaver, or extra levels for a game. What else might appeal to your customers? Be creative. Your bonus doesn&amp;rsquo;t even have to be software-based. Offer a free report about building site traffic with your HTML editor, include an essay on effective time management with your scheduling program, or throw in a small business success guide with your billing program. If you make such programs, you shouldn&amp;rsquo;t have too much trouble coming up with a few pages of text that would benefit your customers. Keep working at it until your offer even looks irresistible to you. If all the bonuses you offer can be delivered electronically, how many can you afford to include? If each one only gains one more customer in a thousand (0.1%), would it be worth the effort over the lifetime of your sales?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;So how do you know if your registration incentives are strong enough? And how do you know if your product is over-crippled? Where do you draw the line? These are tough issues, but there is a good way to handle them if your product is likely to be used over a long period of time, particularly if it&amp;rsquo;s used on a daily basis. Simply make your program gradually increase its registration incentives over time. One easy way to do this is with a delay timer on your nag screens that increases each time the program is run. Another approach is to disable certain features at set intervals. You begin by disabling non-critical features and gradually move up to disabling key functionality. The program becomes harder and harder to continue using for free, so the benefits of registering become more and more compelling. Instead of having your program completely disable itself after your trial period, you gradually degrade its usability with additional usage.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This approach can be superior to a strict 30-day trial, since it allows your program to still be used for a while, but after prolonged usage it becomes effectively unusable. However, you don&amp;rsquo;t simply shock the user by taking away all the benefits s/he has become accustomed to on a particular day. Instead, you begin with a gentle reminder that becomes harder and harder to ignore. There may be times when your 30-day trial shuts off at an inconvenient time for the user, and you may lose a sale as a result. For instance, the user may not have the money at the time, or s/he may be busy at the trial&amp;rsquo;s end and forget to register. In that case s/he may quickly replace what was lost with a competitor&amp;rsquo;s trial version. The gradual degradation approach allows the user to continue using your product, but with increasing difficulty over time. Eventually, there is a breaking point where the user either decides to buy or to stop using the program completely, but this can be done within a window of time at the user&amp;rsquo;s convenience.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Hopefully this article has gotten you thinking creatively about all the overlooked ways you can entice people to buy your shareware products. The most important thing you can do is to begin seeing your products through your customers&amp;rsquo; eyes. What additional motivation would convince you to buy? What would represent an irresistible offer to you? There is no limit to how many incentives you can add. Don&amp;rsquo;t stop at just one or two; instead, give the customer a half dozen or more reasons to buy, and you&amp;rsquo;ll see your registration rate soar. Is it worth spending a day to do this? I think so.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>File sync is very slow</title>
   <link href="https://blog.kowalczyk.info/til-file-sync-is-very-slow.html" rel="alternate"></link>
   <updated>2025-07-17T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-17:/til-file-sync-is-very-slow.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-file-sync-is-very-slow&#34;&gt;&#xA;&lt;div&gt;I&amp;rsquo;m working on a Go library &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/kjk/common/tree/main/appendstore&#34;&gt;appendstore&lt;/a&gt; for append-only store of lots of things in a single file.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To make things as robust as possible I was calling &lt;code&gt;os.File.Sync()&lt;/code&gt; after each append. &lt;code&gt;Sync()&lt;/code&gt; is waiting until the data is acknowledged as truly, really written to disk (as opposed to maybe floating somewhere in disk drive&amp;rsquo;s write buffer).&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Oh boy, is it slow. A test of appending 1000 records would take over 5 seconds.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;After removing the &lt;code&gt;Sync()&lt;/code&gt; it would drop to 5 milliseconds. 1000x faster.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I made sync optional - it&amp;rsquo;s now up to the user of the library to pick it, defaults to non-sync.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Is it unsafe now? Well, the reality is that it probably doesn&amp;rsquo;t matter. I don&amp;rsquo;t think lots of software does the sync due to slowness and the world still runs.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Desktop UI frameworks written by a single person</title>
   <link href="https://blog.kowalczyk.info/a-yyvi/desktop-ui-frameworks-written-by-a-single-person.html" rel="alternate"></link>
   <updated>2025-07-09T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-09:/a-yyvi/desktop-ui-frameworks-written-by-a-single-person.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;yyvi&#34;&gt;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;less-known-desktop-ui-frameworks&#34;&gt;&lt;div&gt;Less known desktop UI frameworks&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#less-known-desktop-ui-frameworks&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Writing desktop software is hard. The UI technologies of Windows or MacOS are awful compared to web technology.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;What can trivially be done with HTML/CSS/JavaScript in few minutes can take hours using Windows&amp;rsquo;s win32 APIs or Mac&amp;rsquo;s Cocoa.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That&amp;rsquo;s why the default technology for desktop apps, especially cross-platform, is Electron: a Chrome browser combined with Node runtime.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The problem is that it&amp;rsquo;s bloaty: each app is a unique build of Chrome with a little bit of application code. Chrome is over 100MB so many apps ship less than 1MB of code in a 100M wrapper.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;People tried to address the problem of poor OS APIs by writing UI frameworks, often meant to be cross-platform.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You&amp;rsquo;ve heard about QT, GTK, wxWindows.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The problem with those is that they are also old, their APIs are not the greatest either and they are bloaty as well.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;There just doesn&amp;rsquo;t seem to be a good option.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Writing your own framework seems impossible due to the size of task.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;But is it?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;ll show a couple of less-known UI frameworks written mostly be a single person, often done simply to enable writing an application.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;swell-in-wdl&#34;&gt;&lt;div&gt;SWELL in WDL&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#swell-in-wdl&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://www.cockos.com/wdl/&#34;&gt;WDL&lt;/a&gt; is interesting. Justin Frankel, the guy who created Winamp, has a repository of C++ code he uses in different projects.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;After selling Winamp to AOL, a side quest of writing file sharing application, getting fired from AOL for writing file sharing application, he started a company building &lt;a target=&#34;_blank&#34; href=&#34;https://www.reaper.fm/&#34;&gt;Reaper&lt;/a&gt; a digital audio workstation software for Windows.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Winamp is a win32 API program and so is Reaper. At some point Justin decided to make a Mac version but by then he had a lot of code heavily using win32 APIs.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;So he did what anyone in his position would: he implemented win32 APIs for Mac OS and Linux and called it SWELL - Simple Windows Emulation Layer.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Ok, actually no-one else would do it. It was an insane idea but it worked.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s important to not over-state SWELL capabilities. It&amp;rsquo;s not Wine. You can&amp;rsquo;t take any win32 program and recompile for Mac with SWELL.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Frankel is insanely pragmatic and so is his code. SWELL only implements the subset of APIs he uses in Reaper.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;At the same time Reaper is a big app so if SWELL works for Reaper, it could work for your app.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;WDL is &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/justinfrankel/WDL&#34;&gt;open-source&lt;/a&gt; using permissive MIT license.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;sublime-text&#34;&gt;&lt;div&gt;Sublime Text&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#sublime-text&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;For a few years &lt;a target=&#34;_blank&#34; href=&#34;https://www.sublimetext.com/&#34;&gt;Sublime Text&lt;/a&gt; was THE programmer&amp;rsquo;s editor.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It was written by a single developer in C++ and he wrote a &lt;a target=&#34;_blank&#34; href=&#34;https://news.ycombinator.com/item?id=2822114&#34;&gt;custom UI toolkit&lt;/a&gt; for it. Not open source but its existence shows it can be done.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;10x-editor&#34;&gt;&lt;div&gt;10x Editor&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#10x-editor&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Less known that Sublime Text, &lt;a target=&#34;_blank&#34; href=&#34;https://www.10xeditor.com/&#34;&gt;10x Editor&lt;/a&gt; is a Windows only editor specialized for large C/C++ code bases.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Also written by a single person and with &lt;a target=&#34;_blank&#34; href=&#34;https://www.10xeditor.com/about.htm#:~:text=with%20a%20custom%20UI%20system&#34;&gt;custom UI system&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;rad-debugger&#34;&gt;&lt;div&gt;RAD Debugger&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#rad-debugger&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/EpicGamesExt/raddebugger&#34;&gt;RAD Debugger&lt;/a&gt; is an open-source Windows debugger for C/C++ apps written in C by mostly a single person.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It implements a &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/EpicGamesExt/raddebugger/tree/master/src/ui&#34;&gt;custom UI framework&lt;/a&gt; based on &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/EpicGamesExt/raddebugger/tree/master/src/render&#34;&gt;3D renderer&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The UI is integral part of the the app but the code is well structured so you probably can take just their UI / render code and use it in your own C / C++ app.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Currently the app / UI is only for Windows but it&amp;rsquo;s designed to be cross-platform and they are working on porting the renderer to Mac OS / Linux.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;They use permissive MIT license and everything is written in C.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;dear-imgui&#34;&gt;&lt;div&gt;Dear ImGUI&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#dear-imgui&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/ocornut/imgui&#34;&gt;Dear ImGui&lt;/a&gt; is a newer cross-platform, UI framework in C++. Open source, permissive MIT license.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Written by mostly a single person.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;ghostty&#34;&gt;&lt;div&gt;Ghostty&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#ghostty&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/ghostty-org/ghostty&#34;&gt;Ghostty&lt;/a&gt; is a cross-platform terminal emulator and UI. It&amp;rsquo;s written in Zig by mostly a single person and uses it&amp;rsquo;s own low-level &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/ghostty-org/ghostty/tree/main/src/renderer&#34;&gt;GPU renderer&lt;/a&gt; for the UI.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;file-pilot&#34;&gt;&lt;div&gt;File Pilot&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#file-pilot&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://filepilot.tech/&#34;&gt;File Pilot&lt;/a&gt; is a file manager for Windows with custom UI framework written on top of OpenGL. Based on &lt;a target=&#34;_blank&#34; href=&#34;https://www.youtube.com/watch?v=bUOOaXf9qIM&#34;&gt;this talk&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;you-too-can-write-your-own-ui-framework&#34;&gt;&lt;div&gt;You too can write your own UI framework&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#you-too-can-write-your-own-ui-framework&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;At first the idea of writing your own UI framework seems impossibly daunting.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;What I&amp;rsquo;m hoping to show is that if you&amp;rsquo;re ambitious enough it&amp;rsquo;s possible to build cross platform desktop apps that are not just bloated 100MB Chrome wrappers around few kilobytes of custom code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;m not saying it&amp;rsquo;s a simple thing, just that enough people did it that it&amp;rsquo;s possible.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It shouldn&amp;rsquo;t be necessary but both Microsoft and Apple have tragically dropped the ball on providing decent, high-performance UI libraries for their OS.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Microsoft even writes their own apps, like Teams, in web technologies.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Thanks to open source you&amp;rsquo;re not at the starting line.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You can just use Dear ImGUI or WDL&amp;rsquo;s SWELL.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Or you can extract the UI code from RAD Debugger or Ghostty (if you write in Zig).&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Or you can look at how their implementation to speed up your own design and implementation.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Evolving Edna Ask AI UI</title>
   <link href="https://blog.kowalczyk.info/article/d-2025-07-09/evolving-edna-ask-ai-ui.html" rel="alternate"></link>
   <updated>2025-07-09T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-09:/article/d-2025-07-09/evolving-edna-ask-ai-ui.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;d-2025-07-09&#34;&gt;&#xA;&lt;div&gt;This is a real life example of tweaking UI in &lt;a target=&#34;_blank&#34; href=&#34;https://edna.arslexis.io&#34;&gt;Edna&lt;/a&gt;, my note taking application with super powers.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Ask AI is a simple AI chat: you write a question, send it to LLM model and get a response.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Here&amp;rsquo;s my first version of the UI:&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;img class=&#34;blog-img&#34; src=&#34;/img/edna-ask-ui-1.png&#34; alt=&#34;&#34; /&gt;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;What is good and bad about this version?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;strong&gt;Good&lt;/strong&gt;: there&amp;rsquo;s a &lt;code&gt;learn more&lt;/code&gt; link. This is not an obvious feature because you need to pick a model and provide an API key. An easy access to an explanation is good.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;strong&gt;Bad&lt;/strong&gt;: It&amp;rsquo;s not clear enough that you need to provide an API key. To make things even more confusing, for models from OpenAI or xAI you can use either OpenAI/xAI key or OpenRouter key. Hence the &lt;code&gt;Use OpenRouter&lt;/code&gt; checkbox. I decided to make things more explicit:&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;img class=&#34;blog-img&#34; src=&#34;/img/edna-ask-ai-2.png&#34; alt=&#34;&#34; /&gt;&#xA;I think it&amp;rsquo;s clearer.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Checkbox is gone. Now I just ask for one or the other and will use whichever is given.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;A &lt;code&gt;learn more&lt;/code&gt; links to section of the docs explaining how to get API key and answering basic questions about API keys. In fact, there are duplicate links to make sure the user doesn&amp;rsquo;t miss them.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Added an error message if no API key is yet provided.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Added explicit placeholder &lt;code&gt;Enter OpenAI API key&lt;/code&gt; text in input field.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;All to make sure that if someone doesn&amp;rsquo;t know about API keys, the information is easy to reach.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Implementing UI translation in SumatraPDF, a C++ Windows application</title>
   <link href="https://blog.kowalczyk.info/a-vn0v/implementing-ui-translation-in-sumatrapdf-a-c-windows-application.html" rel="alternate"></link>
   <updated>2025-07-08T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-08:/a-vn0v/implementing-ui-translation-in-sumatrapdf-a-c-windows-application.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;vn0v&#34;&gt;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;translating-user-interface-of-sumatrapdf&#34;&gt;&lt;div&gt;Translating user interface of SumatraPDF&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#translating-user-interface-of-sumatrapdf&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://www.sumatrapdfreader.org/free-pdf-reader&#34;&gt;SumatraPDF&lt;/a&gt; is the best PDF/eBook/Comic Book viewer for Windows. It&amp;rsquo;s small, fast, full of features, free and open-source.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It became popular enough that it made sense to translate the UI for non-English users. Currently we support 72 languages.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This article describes how I designed and implemented a translation system in SumatraPDF, a native win32 C++ Windows application.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;hard-things-about-translating-the-ui&#34;&gt;&lt;div&gt;Hard things about translating the UI&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#hard-things-about-translating-the-ui&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;There are 2 hard things about translating an application&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;code for translation system (extracting strings to translate, translate strings from English to user&amp;rsquo;s language)&lt;/li&gt;&#xA;&lt;li&gt;translating them into many languages&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;extracting-strings-to-translate-from-source-code&#34;&gt;&lt;div&gt;Extracting strings to translate from source code&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#extracting-strings-to-translate-from-source-code&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Currently there are 381 strings in SumatraPDF subject to translation. It&amp;rsquo;s important that the system requires the least amount of effort when adding new strings to translate.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Every string that needs to be translated is marked in &lt;code&gt;.cpp&lt;/code&gt; or &lt;code&gt;.h&lt;/code&gt; file with one of two macros:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;_TRA(&amp;quot;Rename&amp;quot;)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;_TRN(&amp;quot;Open&amp;quot;)&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;I have a script that extracts those strings from source files. Mine is written in Go but it could just as well be Python or JavaScript. It&amp;rsquo;s a simple regex job.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;code&gt;_TR&lt;/code&gt; stands for &amp;ldquo;translation&amp;rdquo;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;code&gt;_TRA(s)&lt;/code&gt; expands into &lt;code&gt;const char* trans::GetTranslation(const char* str)&lt;/code&gt; function which returns &lt;code&gt;str&lt;/code&gt; translated to current UI language.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We auto-detect language at startup based on Windows settings and allow the user to explicitly set UI language.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For English we just return the original string.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If a string to be translated is e.g. a part of &lt;code&gt;const char* array[]&lt;/code&gt;, we can&amp;rsquo;t use &lt;code&gt;trans::GetTranslation()&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For cases like that we have &lt;code&gt;_TRN()&lt;/code&gt; which expands to English string. We have to write code to translate it at some point.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Adding new strings is therefore as simple as wrapping them in &lt;code&gt;_TRA()&lt;/code&gt; or &lt;code&gt;_TRN()&lt;/code&gt; macros.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;translating-strings-into-many-languages&#34;&gt;&lt;div&gt;Translating strings into many languages&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#translating-strings-into-many-languages&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Now that we&amp;rsquo;ve extracted strings to be translated, we need to translate them into 72 languages.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;SumatraPDF is a free, open-source program. I don&amp;rsquo;t have a budget to hire translators. I don&amp;rsquo;t have a budget, period.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The only option was to get help from SumatraPDF users.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It was vital to make it very easy for users to send me translations. I didn&amp;rsquo;t want to ask them, for example, to download some translation software.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;design-and-implementation-of-apptranslator-web-app&#34;&gt;&lt;div&gt;Design and implementation of AppTranslator web app&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#design-and-implementation-of-apptranslator-web-app&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;I couldn&amp;rsquo;t find a really simple software for crowd sourcing translations so I wrote my own: &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/kjk/apptranslator&#34;&gt;https://github.com/kjk/apptranslator&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You can see it in action: &lt;a target=&#34;_blank&#34; href=&#34;https://www.apptranslator.org/app/SumatraPDF&#34;&gt;https://www.apptranslator.org/app/SumatraPDF&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I designed it to be generic but I don&amp;rsquo;t think anyone else is using it.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;AppTranslator is simple. Per &lt;a target=&#34;_blank&#34; href=&#34;https://tools.arslexis.io/wc/&#34;&gt;https://tools.arslexis.io/wc/&lt;/a&gt;:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;4k lines of Go server code&lt;/li&gt;&#xA;&lt;li&gt;451 lines of html code&lt;/li&gt;&#xA;&lt;li&gt;a single dependency: bootstrap CSS framework (the project is old)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s simple because I don&amp;rsquo;t want to spend a lot of time writing translation software. It&amp;rsquo;s just a side project in service of the goal of translating SumatraPDF.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Login is exclusively via GitHub.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It doesn&amp;rsquo;t even use a database. Like in Redis, changes are stored as a series of operations in an append-only log. We keep the whole state in memory and re-create it from the log at startup.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Main operation is &lt;code&gt;translate a string from English to language X&lt;/code&gt; represented as &lt;code&gt;[kOpTranslation, english string, language, translation, user who provided translation]&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;When user provides a translation in the web UI, we send an API call to the server which appends the translation operation to the log.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Simple and reliable.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Because the code is written in Go, it&amp;rsquo;s very fast and memory efficient. When running it uses mere megabytes of RAM. It can comfortably run on the smallest 256 MB VPS server.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I backup the log to S3 so if the server ever fails, I can re-install the program on a new server and re-download the translations from S3.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I provide RSS feed for each language so that people who provide translations can monitor for new strings to be translated.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;sending-strings-for-translation-and-receiving-translations&#34;&gt;&lt;div&gt;Sending strings for translation and receiving translations&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#sending-strings-for-translation-and-receiving-translations&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;So I have a web app for collecting translations and a script that extracts strings to be translated from source code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;How do they connect?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;AppTranslator has an API for submitting the current set of strings to be translated in the simplest possible format: a line for each string (I ensure there are no newlines in the string itself by escaping them with &lt;code&gt;\n&lt;/code&gt;)&lt;/div&gt;&#xA;&#xA;&lt;div&gt;API is password protected because only I can submit the strings.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The server compares the strings sent with the current set and records a difference in the log.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It also sends a response with translations. Again the simplest possible format:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;AppTranslator: SumatraPDF&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;651b739d7fa110911f25563c933f42b1d37590f8&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:%s annotation. Ctrl+click to edit.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;am:%s մեկնաբանություն: Ctrl+քլիք՝ խմբագրելու համար:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ar:ملاحظة %s. اضغط Ctrl للتحرير.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;az:Qeyd %s. Düzəliş etmək üçün Ctrl+düyməyə basın.&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;As you can see:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;a string to translate is on a line starting with :&lt;/li&gt;&#xA;&lt;li&gt;is followed by translations of that strings in the format: &lt;code&gt;${lang}: ${translation}&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;An optimization: &lt;code&gt;651b739d7fa110911f25563c933f42b1d37590f8&lt;/code&gt; is a hash of this response. If I submit this hash with my request and translations didn&amp;rsquo;t change on the server, the response is empty.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;implementing-c-part-of-translation-system&#34;&gt;&lt;div&gt;Implementing C++ part of translation system&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#implementing-c-part-of-translation-system&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;So now I have a text file with translation downloaded from the server. How do I get a translation in my C++ code?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;As with everything in SumatraPDF, I try to do things in a simple and efficient way.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The whole &lt;code&gt;Translation.cpp&lt;/code&gt; is only 239 lines of code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The core of translation system is &lt;code&gt;const char* trans::GetTranslation(const char* s);&lt;/code&gt; function.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I embed the translations in exact the same format as received from AppTranslator in the executable as data file in resources.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If the UI language is English, we do nothing. &lt;code&gt;trans::GetTranslation()&lt;/code&gt; returns its argument.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;When we switch the language, we load the translations from resources and build an index:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;an array of English strings&lt;/li&gt;&#xA;&lt;li&gt;an array of corresponding translations&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;Both arrays use my own &lt;a href=&#34;/a-u2y2/implementation-of-optimized-vector-of-strings-in-c-in-sumatrapdf.html&#34;&gt;StrVec&lt;/a&gt; class optimized for storing an array of strings.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To find a translation we scan the first array to find an index of the string and return translation from the second array, at the same index.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Linear scan seems like it would be slow but it isn&amp;rsquo;t.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;resizing-dialogs&#34;&gt;&lt;div&gt;Resizing dialogs&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#resizing-dialogs&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;I have a few dialogs defined in &lt;code&gt;SumatraPDF.rc&lt;/code&gt; file.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The problem with dialogs is that position of UI elements is fixed.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;A translated string will almost certainly have a different size than the English string which will mess up fixed layout.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Thankfully someone wrote DialogSizer that smartly resizes dialogs and solves this problem.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;the-evolution-of-a-solution&#34;&gt;&lt;div&gt;The evolution of a solution&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#the-evolution-of-a-solution&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;no-apptranslator&#34;&gt;&lt;div&gt;No AppTranslator&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#no-apptranslator&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;My initial implementation was simpler. I didn&amp;rsquo;t yet have AppTranslator so I stored the strings in a text file in repository in the same format as what I described above.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;People would download it, make changes using a text editor and send me the file via email which I would then checkin.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It worked for a while but it became worse over time. More strings, more languages created more work for me to manually manage e-mail submissions.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I decided to automate the process.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;code-generation&#34;&gt;&lt;div&gt;Code generation&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#code-generation&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;My first implementation of C++ side used code generation instead of embedding the text file in resources.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;My Go script would generate C++ source code files with static &lt;code&gt;const char* []&lt;/code&gt; arrays.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This worked well but I decided to improve it further by making the code use the text file with translations embedded in the app.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The main motivation for the change was to open a possibility of downloading latest translations from the server to fix the problem of translations not being all ready when I build the release executable.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I haven&amp;rsquo;t done that yet but it&amp;rsquo;s now easier to implement given that the format of strings embedded in the exe is the same as the one I can download from AppTranslator.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;only-utf-8&#34;&gt;&lt;div&gt;Only utf-8&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#only-utf-8&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;SumatraPDF started by using both &lt;code&gt;WCHAR*&lt;/code&gt; Unicode strings and &lt;code&gt;char*&lt;/code&gt; utf8 strings.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For that reason the translation system had to support returning translation in both &lt;code&gt;WCHAR*&lt;/code&gt; and &lt;code&gt;char*&lt;/code&gt; version.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Over time I refactored the code to use mostly utf8 and at some point I no longer needed to support &lt;code&gt;WCHAR*&lt;/code&gt; version.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That made the code even smaller and reduced memory usage.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;the-experience&#34;&gt;&lt;div&gt;The experience&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#the-experience&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;m happy how things turned out.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://www.apptranslator.org/app/SumatraPDF&#34;&gt;AppTranslator&lt;/a&gt; proved to be reliable and hassle free. It runs for many years now and collected 35440 string translations from users.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I automated everything so that all I need to do is to periodically re-run the script that extracts strings from source code, uploads them to AppTranslator and downloads latest translations.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;One problem is that translations are not always ready in time for release so I make a release and then people start translating strings added since last release.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;ve considered downloading the latest translations from the server, in addition to embedding them in an executable at the time of building the app.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;would-i-do-the-same-today&#34;&gt;&lt;div&gt;Would I do the same today?&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#would-i-do-the-same-today&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;While AppTranslator is reliable and doesn&amp;rsquo;t require on-going work, it would be better to not have to run a server at all.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The world has changed since I started SumatraPDF.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Namely: people are comfortable using GitHub and you can edit files directly in GitHub UI. It&amp;rsquo;s not a great experience but it works.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;One option would be to generate a translation text file for each language, in this format:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:first untranslated string&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:second untranslated string&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:first translated string&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;translation of first string&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;:second translated string&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;translation of second string&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Untranslated strings are listed at the top, to make it easier to find.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;A link would send a translator directly to edit this file in GitHub UI.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;When translator saves translations, it creates a PR for me to review and merge.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;the-roads-not-taken&#34;&gt;&lt;div&gt;The roads not taken&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#the-roads-not-taken&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;blockquote&gt;&#xA;&lt;div&gt;But why did you re-invent everything? You should do X instead.&lt;/div&gt;&#xA;&lt;/blockquote&gt;&#xA;&#xA;&lt;div&gt;All other X that I know about suck.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;using-per-language-rc-resource-files&#34;&gt;&lt;div&gt;Using per-language .rc resource files&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#using-per-language-rc-resource-files&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Traditional way of localizing / translating Window GUI apps is to store all strings and dialog definitions in an &lt;code&gt;.rc&lt;/code&gt; file. Each language gets its own &lt;code&gt;.rc&lt;/code&gt; file (or files) and the program picks the right resource based on a language.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This doesn&amp;rsquo;t solve the 2 hard problems:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;having an easy way to add strings for translations&lt;/li&gt;&#xA;&lt;li&gt;having an easy way for users to provide translations&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;xml-horror-show&#34;&gt;&lt;div&gt;XML horror show&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#xml-horror-show&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;There was a dark time when the world was under the iron grip of XML fanaticism.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Everything had to be an XML file even when it was the worst possible solution for the problem.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;XML doesn&amp;rsquo;t solve the 2 hard problems and a string storage format is an absolute nightmare for human editing.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;gnu-gettext&#34;&gt;&lt;div&gt;GNU gettext&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#gnu-gettext&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;There&amp;rsquo;s a C library gettext that uses &lt;code&gt;.po&lt;/code&gt; files.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This is much saner solution than XML horror show. &lt;code&gt;.po&lt;/code&gt; files are relatively simple text format. The code is already written.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Warning: tooting my own horn.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;My format is better. It&amp;rsquo;s easier for people to edit, it&amp;rsquo;s easier to write code to parse it. &lt;a target=&#34;_blank&#34; href=&#34;https://github.com/autotools-mirror/gettext&#34;&gt;This&lt;/a&gt; looks like many times more than 239 lines of code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Ok, gettext probably does a bit more than my code, but clearly nothing than I need.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It also doesn&amp;rsquo;t solve the 2 hard problems. I would still have to write code to extract strings from source code and build a way to allow users to translate them easily.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Calling Grok, OpenAI, Anthropic, Google, OpenRouter API from the browser</title>
   <link href="https://blog.kowalczyk.info/til-calling-grok-openai-anthropic-google-openrouter-api-from-the-browser.html" rel="alternate"></link>
   <updated>2025-07-08T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-08:/til-calling-grok-openai-anthropic-google-openrouter-api-from-the-browser.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-calling-grok-openai-anthropic-google-openrouter-api-from-the-browser&#34;&gt;&#xA;&lt;div&gt;Here&amp;rsquo;s what I learned about calling LLM APIs from the browser when building AI chat functionality in my note taking app &lt;a target=&#34;_blank&#34; href=&#34;https://edna.arslexis.io&#34;&gt;Edna&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The API I care about is getting LLM response to a question in a streaming way.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;OpenAI pioneered this and created &lt;code&gt;https://api.openai.com/v1/chat/completions&lt;/code&gt; POST API. Others created a compatible API for their LLM to make it easy for programmers to migrate. &lt;a target=&#34;_blank&#34; href=&#34;https://x.ai/&#34;&gt;xAI&lt;/a&gt; has &lt;code&gt;https://api.x.ai/v1/chat/completions&lt;/code&gt; for Grok and &lt;a target=&#34;_blank&#34; href=&#34;https://openrouter.ai/&#34;&gt;OpenRouter&lt;/a&gt; has &lt;code&gt;https://openrouter.ai/api/v1/chat/completions&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Google and Anthropic have similar APIs but they use CORS to disallow calling them from the browser. Baffling restriction. For now I decided to not support them directly. I could route the requests via the server but I can use OpenRouter instead.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;ve seen TypingMind call Google API from the browser but using a different API endpoint. Again, for now I decided to not support Google directly.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://openrouter.ai/&#34;&gt;OpenRouter&lt;/a&gt; is an interesting service and business. They provide unified API for lots of different models so I can use Google or Anthropic APIs via OpenRouter and lots of other models. They charge 5% on top of what they pay the providers, which is reasonable if you consider that they probably pay ~3% for processing credit card fees.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For now I support OpenAI and Grok directly and everyone else via OpenRouter.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Increase open file limit on Ubuntu Linux</title>
   <link href="https://blog.kowalczyk.info/til-increase-open-file-limit-on-ubuntu-linux.html" rel="alternate"></link>
   <updated>2025-07-07T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-07:/til-increase-open-file-limit-on-ubuntu-linux.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-increase-open-file-limit-on-ubuntu-linux&#34;&gt;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;what-and-why-of-open-file-limit&#34;&gt;&lt;div&gt;What and why of open file limit&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#what-and-why-of-open-file-limit&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;If you run a webapp on a Linux server, your webapp needs to open files and make network connections.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Most Linux servers have horrible default for this and limit the number of opened files at the same time to  e.g. 1024.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To check the limit run: &lt;code&gt;ulimit -n&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;1024 makes sense if it&amp;rsquo;s a shared computer used by multiple users, to protect the system from abusive user. It doesn&amp;rsquo;t make sense if the server is used for running a web app which can run into this limit and silently fail because it can&amp;rsquo;t open a file or a network connection.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;What is a reasonable limit? No one knows but I set mine high, to at least 65 thousand. The more RAM you have, the higher the limit can be. It also depends on your app: if it opens a lot of files and network connections, you need higher limit.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;how-to-change-open-file-limit-on-ubuntu&#34;&gt;&lt;div&gt;How to change open file limit on Ubuntu&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#how-to-change-open-file-limit-on-ubuntu&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;1. Edit the system limits configuration:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo nano /etc/security/limits.conf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;2. Add at the end of file:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;*       soft    nofile  65535&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;*       hard    nofile  65535&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;3. Edit PAM configuration file:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo nano /etc/pam.d/common-session&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;4. Add at the end of file:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;session required pam_limits.so&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;5. Edit the limits configuration file for systemd:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo nano /etc/systemd/system.conf&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;6. Add at the end of file:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DefaultLimitNOFILE=65535&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;7. Reboot:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo reboot&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;It&amp;rsquo;s way too complicated but that&amp;rsquo;s Linux for you.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Case study of over-engineered C++ code</title>
   <link href="https://blog.kowalczyk.info/a-aiow/case-study-of-over-engineered-c-code.html" rel="alternate"></link>
   <updated>2025-07-07T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-07:/a-aiow/case-study-of-over-engineered-c-code.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;aiow&#34;&gt;&#xA;&lt;div&gt;You&amp;rsquo;ve heard of over-engineered, unnecessarily complex code but what exactly is it?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I believe it&amp;rsquo;s best to show by example.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;While it&amp;rsquo;s not my intention to criticize other people&amp;rsquo;s code, I think it&amp;rsquo;s better to show  code and how to improve it rather than vaguely talk about principles.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The code that I consider over-engineered:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/horsicq/Formats/blob/master/xbinary.h&#34;&gt;xbinary.h&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/horsicq/Formats/blob/master/images/xbmp.h&#34;&gt;xbmp.h&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://github.com/horsicq/Formats/blob/master/images/xbmp.cpp&#34;&gt;xbmp.cpp&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;the-problem-it-s-trying-to-solve&#34;&gt;&lt;div&gt;The problem it&amp;rsquo;s trying to solve&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#the-problem-it-s-trying-to-solve&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;This code detects file format from file content. Are the bytes an audio wav file? A jpeg image?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In addition, it extracts some properties of the file format e.g. a dimension of the image file.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;over-engineered-implementation&#34;&gt;&lt;div&gt;Over-engineered implementation&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#over-engineered-implementation&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;If you&amp;rsquo;re C++ programmer it&amp;rsquo;s natural to use object oriented design. You create &lt;code&gt;XBinary&lt;/code&gt; base class with some virtual methods and then write a class for each format that inherits from &lt;code&gt;XBinary&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Here&amp;rsquo;s just a small part:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBinary&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FT&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getFileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ENDIAN&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getEndian&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// ... much more stuff&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;And implementation for detecting BMP images:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBMP&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XBinary&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;XBinary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;FT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XBMP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getFileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FT_BMP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;XBinary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MODE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XBMP&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;getMode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XBinary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MODE_DATA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;over-engineering-in-the-small-unnecessary-virtual-functions&#34;&gt;&lt;div&gt;Over-engineering in the small: unnecessary virtual functions&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#over-engineering-in-the-small-unnecessary-virtual-functions&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;This code is over-engineered in the small.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Notice that file type or mode are static per file format. They most likely do not depend on the data.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We can easily eliminate virtual calls by storing this info as class members.&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBinary&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;private&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_fileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;MODE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;getFileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_fileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;MODE&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getMode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBMP&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;public&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XBinary&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;XBMP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;fileType&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FT_BMP&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;mode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XBinary&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;::&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MODE_DATA&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;We replaced multiple virtual methods with a single non-virtual method in base class.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That is a saving in both code size and code speed.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Parsing and compiling more stuff requires compiler to do more work which takes more time.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;removing-getter-methods&#34;&gt;&lt;div&gt;Removing getter methods&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#removing-getter-methods&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;We don&amp;rsquo;t need the method that just returns the value of a variable.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;A function is necessary if it does some computation on data. It doesn&amp;rsquo;t happen here so it&amp;rsquo;s just bad habit of mindlessly adding unnecessary code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We can simplify by making class members public:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBinary&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;public&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;MODE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;over-engineering-in-the-big-design&#34;&gt;&lt;div&gt;Over-engineering in the big: design&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#over-engineering-in-the-big-design&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;code&gt;XBinary&lt;/code&gt; defines 9 virtual classes, each to get small bits of information about the format:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBMP&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FT&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getFileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QString&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getMIMEString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QString&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getArch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MODE&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getMode&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ENDIAN&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getEndian&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QString&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getFileFormatExt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QString&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getFileFormatExtsString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;_MEMORY_MAP&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getMemoryMap&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;MAPMODE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mapMode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;MAPMODE_UNKNOWN&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PDSTRUCT&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pPdStruct&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;nullptr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;QString&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getVersion&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;An observation: they are all cheap to compute. Typically reading a few bytes of memory.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Instead of providing a function for each piece of information, we could have one  function that returns everything.&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;FormatInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FT&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fileType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;QString&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;mimeString&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// ... the other 7 values&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBMP&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FormatInfo&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getFormatInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;We save lots of code by consolidating 9 different functions into one. We also simplified the API and I believe someone new to the library would figure out how to use smaller interface faster.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Each format also provides a per-format data. &lt;code&gt;XBMP&lt;/code&gt; has:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBMP&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BMPFILEHEADER&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getFileHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BMPINFOHEADER&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getInfoHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Again, we could combine this into one function:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XbmpInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BMPFILEHEADER&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fileHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BMPINFOHEADER&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;infoHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBMP&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;XbmpInfo&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getXbmpInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;virtual&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FormatInfo&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getFormatInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;But wait, we can combine this info a single function:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XbmpInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FormatInfo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;formatInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BMPFILEHEADER&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fileHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BMPINFOHEADER&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;infoHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XBMP&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;XbmpInfo&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;getXbmpInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;In fairness, we&amp;rsquo;ve lost ability to use the API in a certain way. Before if code was only interested in common properties in &lt;code&gt;FormatInfo&lt;/code&gt; it could use the same code for every class representing a format. Now it has to know it&amp;rsquo;s calling e.g. &lt;code&gt;XBMP&lt;/code&gt; and get &lt;code&gt;FormatInfo&lt;/code&gt; out of &lt;code&gt;XbmpInfo&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;we-don-t-need-classes-at-all&#34;&gt;&lt;div&gt;We don&amp;rsquo;t need classes at all&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#we-don-t-need-classes-at-all&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;The best part is no part.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If we had to write this code in C, how would we do it?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We could implement each format detector as a single function.&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;XbmpInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;isValid&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;FormatInfo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;formatInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BMPFILEHEADER&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;fileHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;BMPINFOHEADER&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;infoHeader&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;PngInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;XbmpInfo&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;maybeDetectXbmp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataSize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;PngInfo&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;maybeDetectPng&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataSize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;one-function-to-rule-them-all&#34;&gt;&lt;div&gt;One function to rule them all&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#one-function-to-rule-them-all&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;We have a function for each file type, but we can simplify it to a single function that detects the type and returns information for a given file type:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;XbmpInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;PngInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;...&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;InvalidTye&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;c1&#34;&gt;// if not a known format&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;n&#34;&gt;XbmpType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;n&#34;&gt;PngType&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;c1&#34;&gt;// ....&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;FormatInfo&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;enum&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;typ&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;n&#34;&gt;FormatInfo&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;formatInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;union&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;n&#34;&gt;XbmpInfo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;xbmp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&#x9;&lt;span class=&#34;n&#34;&gt;PngInfo&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;png&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;extraInfo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;FormatInfo&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;detectFileFormat&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;data&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;kt&#34;&gt;size_t&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;dataSize&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;The API is now dramatically simpler.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We removed all the classes, all their methods. It&amp;rsquo;s a massive saving in lines of code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You save binary size, you make the code faster but most importantly you save yourself time because this is code you don&amp;rsquo;t have to write.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You can focus on writing the logic for parsing file formats not on incidental complexity of typing up class names and methods.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;why-do-people-over-complicate&#34;&gt;&lt;div&gt;Why do people over-complicate?&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#why-do-people-over-complicate&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Because simplicity is hard.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Because when you have a hammer, everything looks like a nail.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;After you&amp;rsquo;ve read a book on C++, teaching you about inheritance, virtual functions etc. it&amp;rsquo;s only natural to start modeling all problems with class inheritance and virtual functions.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To then come up with a solution that reduces all that to a function requires thinking outside the C++ box.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Thinking outside the box is hard.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Explaining nil interface{} gotcha in Go</title>
   <link href="https://blog.kowalczyk.info/a-d9qh/explaining-nil-interface-gotcha-in-go.html" rel="alternate"></link>
   <updated>2025-07-06T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-06:/a-d9qh/explaining-nil-interface-gotcha-in-go.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;d9qh&#34;&gt;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;explaining-nil-interface-gotcha-in-go&#34;&gt;&lt;div&gt;Explaining nil interface{} gotcha in Go&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#explaining-nil-interface-gotcha-in-go&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;a-footgun&#34;&gt;&lt;div&gt;A footgun&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#a-footgun&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;In Go empty interface is an interface without any methods, typed as &lt;code&gt;interface{}&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;A zero value of &lt;code&gt;interface{}&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// compiler sets this to nil, you could explicitly write = nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;v is nil\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;v is NOT nil\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://arslexis.io/goplayground/#Wq1SoxY4VDh&#34;&gt;Try online&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This prints: &lt;code&gt;v is nil&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;However, this sometimes trips people up:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;nilFoo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// implicilty initialized by compiler to nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;nilFoo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;nilFoo is nil.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;nilFoo is NOT nil.&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;nilFoo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;v is nil\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;v is NOT nil\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://arslexis.io/goplayground/#aKlibKvMIAD&#34;&gt;Try online&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This prints: &lt;code&gt;nilFoo is nil. v is NOT nil&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;On surface level, this is wrong: &lt;code&gt;t&lt;/code&gt; is a &lt;code&gt;nil&lt;/code&gt;. We assigned a &lt;code&gt;nil&lt;/code&gt; to &lt;code&gt;v&lt;/code&gt; but it doesn&amp;rsquo;t equal to &lt;code&gt;nil&lt;/code&gt;?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;How to check if &lt;code&gt;interface{}&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt; of any pointer type?&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;isNilPointer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{})&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;        &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// interface itself is nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reflect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;ValueOf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;i&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;return&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Kind&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;reflect&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Ptr&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;           &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;IsNil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;struct&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;pf&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;pf&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;isNilPointer&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;v is nil pointer\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&#x9;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;v is NOT nil pointer\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#x9;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://arslexis.io/goplayground/#yod9nAh9Qt0&#34;&gt;Try online&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;why&#34;&gt;&lt;div&gt;Why&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#why&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;There&amp;rsquo;s a reason for this perplexing behavior.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;code&gt;nil&lt;/code&gt; is an abstract value. If you come from C/C++ or Java/C#, you might think that this is equivalent of NULL pointer or null reference.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It isn&amp;rsquo;t. &lt;code&gt;nil&lt;/code&gt; is a symbol that represents a zero value of pointers, channels, maps, slices.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Logically &lt;code&gt;interface{}&lt;/code&gt; combines type and value. You can think of it as a tuple &lt;code&gt;(type, value)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;An uninitialized value of &lt;code&gt;interface{}&lt;/code&gt; is a tuple without a type and value &lt;code&gt;(no type, no value)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In Go &lt;code&gt;uninitialized value&lt;/code&gt; is zero value and since &lt;code&gt;nil&lt;/code&gt; is an abstract value representing zero value for several types, it makes sense to use it for zero value of &lt;code&gt;interface{}&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;So: zero value of &lt;code&gt;interface{}&lt;/code&gt; is &lt;code&gt;nil&lt;/code&gt; which is &lt;code&gt;(no type, no value)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;When we assigned &lt;code&gt;nilFoo&lt;/code&gt; to &lt;code&gt;v&lt;/code&gt;, the value is &lt;code&gt;(*Foo, nil)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Are you surprised that &lt;code&gt;(no type, no value)&lt;/code&gt; is not the same as &lt;code&gt;(*Foo, nil)&lt;/code&gt;?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To understand this gotcha, you have to understand two things.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;One: &lt;code&gt;nil&lt;/code&gt; is an abstract value that only has a meaning in context.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Consider this:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ch&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;chan&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;map&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ch&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;fmt&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;Printf&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;ch is equal to m\n&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://arslexis.io/goplayground/#UGxCom422-e&#34;&gt;Try online&lt;/a&gt;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This snippet doesn&amp;rsquo;t even compile: &lt;code&gt;Error:./prog.go:8:11: invalid operation: ch == m (mismatched types chan bool and map[string]bool)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Both &lt;code&gt;ch&lt;/code&gt; and &lt;code&gt;m&lt;/code&gt; are &lt;code&gt;nil&lt;/code&gt; but you can&amp;rsquo;t compare them because they are of different types. &lt;code&gt;nil != nil&lt;/code&gt; because nil is an abstract concept, not an actual value.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Two: &lt;code&gt;nil&lt;/code&gt; value of &lt;code&gt;interface{}&lt;/code&gt; is &lt;code&gt;(no type, no value)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Once you understand the above, you&amp;rsquo;ll understand why &lt;code&gt;nil&lt;/code&gt; doesn&amp;rsquo;t compare to &lt;code&gt;(type, nil)&lt;/code&gt; e.g. &lt;code&gt;(*Foo, nil)&lt;/code&gt; or &lt;code&gt;(map[string]bool, nil)&lt;/code&gt; or &lt;code&gt;(int, 0)&lt;/code&gt; or &lt;code&gt;(string, &amp;quot;&amp;quot;)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;bad-design-or-inevitable-consequence-of-previous-decisions&#34;&gt;&lt;div&gt;Bad design or inevitable consequence of previous decisions?&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#bad-design-or-inevitable-consequence-of-previous-decisions&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Many claim it&amp;rsquo;s a bad design.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;No-one describes what a better design would look like.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Let&amp;rsquo;s play act a Go language designer.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You&amp;rsquo;ve already designed concrete types, you came up with notion of zero value and created nil to denote zero value for pointers, channels, maps, slices.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You&amp;rsquo;re now designing &lt;code&gt;interface{}&lt;/code&gt; as a logical tuple of &lt;code&gt;(type, value)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The zero value is obviously &lt;code&gt;(no type, no value)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You have to figure how to represent the zero value.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;a-different-symbol-for-interface-zero-value&#34;&gt;&lt;div&gt;A different symbol for interface{} zero value&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#a-different-symbol-for-interface-zero-value&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;Instead of using &lt;code&gt;nil&lt;/code&gt; you could create a different symbol e.g. &lt;code&gt;zeroInteface&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You could then write:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;Foo&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;interface&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;zeroInteface&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// this is true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v2&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// tihs is true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;v3&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;==&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;nil&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;c1&#34;&gt;// is it true or not?&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Is this a better design?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I don&amp;rsquo;t think so.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We don&amp;rsquo;t have &lt;code&gt;zeroPointer&lt;/code&gt;, &lt;code&gt;zeroMap&lt;/code&gt;, &lt;code&gt;zeroChanel&lt;/code&gt; etc. so this breaks consistency. It sticks out like a sore &lt;code&gt;zeroInterface&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;And &lt;code&gt;v == nil&lt;/code&gt; is subtle. Not all values wrapped in an &lt;code&gt;interface{}&lt;/code&gt; have zero value of &lt;code&gt;nil&lt;/code&gt;. What should happen if you compare to &lt;code&gt;(int, 0)&lt;/code&gt; given that &lt;code&gt;0&lt;/code&gt; is zero value of &lt;code&gt;int&lt;/code&gt;?&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;damn-the-consistency-let-s-do-what-user-expects&#34;&gt;&lt;div&gt;Damn the consistency, let&amp;rsquo;s do what user expects&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#damn-the-consistency-let-s-do-what-user-expects&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;You could ditch the strict logic of &lt;code&gt;nil&lt;/code&gt; values and special case the &lt;code&gt;if v == nil&lt;/code&gt; for &lt;code&gt;interface{}&lt;/code&gt; to do what people superficially expect to happen.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You then have to answer the question below: what happens when you do &lt;code&gt;if (int, 0) == nil&lt;/code&gt;?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The biggest issue is that you&amp;rsquo;ve lost ability to distinguish between &lt;code&gt;(no type, no value)&lt;/code&gt; and &lt;code&gt;(type, nil)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;They both compare to &lt;code&gt;nil&lt;/code&gt; so how would you test for &lt;code&gt;(no type, no value)&lt;/code&gt; but not &lt;code&gt;(type, nil)&lt;/code&gt;?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It doesn&amp;rsquo;t seem like a better design either.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;your-proposal&#34;&gt;&lt;div&gt;Your proposal&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#your-proposal&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;Now that you understand the problem and seen two ideas for how to fix it, it&amp;rsquo;s your turn to design a better solution.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I tried and the above 2 are the only ideas I had.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We are boxed by existing notions of zero values and using nil to represent them.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;We could explore designs that re-think those assumptions but would that be Go anymore?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s easy to complain that something is a bad design.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s much harder, often impossible, to design something better.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>Size textarea to content</title>
   <link href="https://blog.kowalczyk.info/til-size-textarea-to-content.html" rel="alternate"></link>
   <updated>2025-07-05T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-05:/til-size-textarea-to-content.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;til-size-textarea-to-content&#34;&gt;&#xA;&lt;div&gt;To size &lt;code&gt;textarea&lt;/code&gt; to content:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;textarea&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;n&#34;&gt;field-sizing&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;content&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;min-height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;rem&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#x9;&lt;span class=&#34;k&#34;&gt;max-height&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;70&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;vh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Using tailwindcss: &lt;code&gt;&amp;lt;textarea class=&amp;quot;min-h-[8rem] max-h-[70vh] field-sizing-content&amp;quot;&amp;gt;&amp;lt;/textarea&amp;gt;&lt;/code&gt;&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Needs Chrome 123+, Firefox 126+&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>All about Svelte 5 snippets</title>
   <link href="https://blog.kowalczyk.info/a-mzm1/all-about-svelte-5-snippets.html" rel="alternate"></link>
   <updated>2025-07-03T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-03:/a-mzm1/all-about-svelte-5-snippets.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;mzm1&#34;&gt;&#xA;&lt;div&gt;Snippets are a useful addition to Svelte 5. I use them in my Svelte 5 projects like &lt;a target=&#34;_blank&#34; href=&#34;https://edna.arslexis.io&#34;&gt;Edna&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;snippet-basics&#34;&gt;&lt;div&gt;Snippet basics&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippet-basics&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;A snippet is a function that renders html based on its arguments.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Here&amp;rsquo;s how to define and use a snippet:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;snippet&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Hello &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;!&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/snippet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Andrew&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Amy&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;You can re-use snippets by exporting them:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;script&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;module&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;snippet&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;hello&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;Hello&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&amp;lt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;snippet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;snippets-use-cases&#34;&gt;&lt;div&gt;Snippets use cases&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippets-use-cases&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;snippets-for-less-nesting&#34;&gt;&lt;div&gt;Snippets for less nesting&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippets-for-less-nesting&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Deeply nested html is hard to read.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You can use snippets to extract some parts to make the structure clearer.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For example, you can transform:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;flex justify-end mt-2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;na&#34;&gt;onclick&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onclose&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s&#34;&gt;class=&amp;#34;mr-4&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;px-4&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;py-1&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;border&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;border-black&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;hover:bg-gray-100&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Cancel&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;na&#34;&gt;onclick&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{()&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;emitRename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;s&#34;&gt;disabled=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;!&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;canRename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;px-4 py-1 border border-black hover:bg-gray-50 disabled:text-gray-400 disabled:border-gray-400 disabled:bg-white default:bg-slate-700&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Rename&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;into:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;snippet&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;buttonCancel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;na&#34;&gt;onclick&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;onclose&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s&#34;&gt;class=&amp;#34;mr-4&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;px-4&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;py-1&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;border&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;border-black&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;hover:bg-gray-100&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Cancel&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;button&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/snippet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;snippet&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;buttonRename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;...&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/snippet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;To make this easier to read:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;flex justify-end mt-2&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;buttonCancel&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;buttonRename&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;snippets-replace-default-slot&#34;&gt;&lt;div&gt;snippets replace default &lt;code&gt;&amp;lt;slot/&amp;gt;&lt;/code&gt;&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippets-replace-default-slot&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;In Svelte 4, if you wanted place some HTML inside the component, you used &lt;code&gt;&amp;lt;slot /&amp;gt;&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Let&amp;rsquo;s say you have &lt;code&gt;Overlay.svelte&lt;/code&gt; component used like this:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Overlay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;MyDialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;MyDialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Overlay&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;In Svelte 4, you would use &lt;code&gt;&amp;lt;slot /&amp;gt;&lt;/code&gt; to render children:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;overlay-wrapper&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;slot&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;/&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;code&gt;&amp;lt;slot /&amp;gt;&lt;/code&gt; would be replaced with &lt;code&gt;&amp;lt;MyDialog&amp;gt;&amp;lt;/MyDialog&amp;gt;&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In Svelte 5 &lt;code&gt;&amp;lt;MyDialog&amp;gt;&amp;lt;/MyDialog&amp;gt;&lt;/code&gt; is passed to &lt;code&gt;Overlay.svelte&lt;/code&gt; as &lt;code&gt;children&lt;/code&gt; property so you would change &lt;code&gt;Overlay.svelte&lt;/code&gt; to:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;children&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;$props&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;overlay-wrapper&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;children&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;code&gt;children&lt;/code&gt; property is created by Svelte compiler so you should avoid naming your own props &lt;code&gt;children&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;snippets-replace-named-slots&#34;&gt;&lt;div&gt;snippets replace named slots&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippets-replace-named-slots&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;A component can have a default slot for rendering children and additional named slots.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In Svelte 5 instead of named slots you pass snippets as props.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;An example of &lt;code&gt;Dialog.svelte&lt;/code&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;let&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;children&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;$props&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;();&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;dialog&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;children&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;And use:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;snippet&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;fancy-title&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;My fancy title&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/snippet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Dialog&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Body of the dialog&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;passing-snippets-as-implicit-props&#34;&gt;&lt;div&gt;passing snippets as implicit props&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#passing-snippets-as-implicit-props&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;You can pass &lt;code&gt;title&lt;/code&gt; snippet prop implicitly:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;snippet&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;title&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;fancy-title&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;My fancy title&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/snippet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;Body of the dialog&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;div&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;Dialog&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Because &lt;code&gt;{snippet title()}&lt;/code&gt; is a child or &lt;code&gt;&amp;lt;Dialog&amp;gt;&lt;/code&gt;, we don&amp;rsquo;t have to pass it as explicit &lt;code&gt;title={title}&lt;/code&gt; prop. The compiler does it for us.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;snippets-to-reduce-repetition&#34;&gt;&lt;div&gt;snippets to reduce repetition&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippets-to-reduce-repetition&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Here&amp;rsquo;s part of how I render &lt;a target=&#34;_blank&#34; href=&#34;https://tools.arslexis.io/&#34;&gt;https://tools.arslexis.io/&lt;/a&gt;&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;#&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;snippet&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;tr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;text-left align-top&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;      &lt;span class=&#34;p&#34;&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;a&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;font-semibold whitespace-nowrap&amp;#34;&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;href&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;url&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;lt;/a&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;class&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;pl-4 align-top&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;{&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;@html&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;desc&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;td&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;tr&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;/snippet&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;unzip&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/unzip/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;unzip a file in the browser&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;kd&#34;&gt;@render&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;row&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;wc&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/wc/&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;like &amp;lt;tt&amp;gt;wc&amp;lt;/tt&amp;gt;, but in the browser&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;It saves me copy &amp;amp; paste of the same HTML and makes the structure more readable.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;snippets-for-recursive-rendering&#34;&gt;&lt;div&gt;snippets for recursive rendering&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippets-for-recursive-rendering&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Sometimes you need to render a recursive structure, like nested menus or file tree.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In Svelte 4 you could use &lt;code&gt;&amp;lt;svelte:self&amp;gt;&lt;/code&gt; but the downside of that is that you create multiple instances of the component. That means that the state is also split among multiple instances.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That makes it harder to implement functionality that requires a global view of the structure, like keyboard navigation.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;With snippets you can render things recursively in a single instance of the component.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I used it to implement nested context menus.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;snippets-to-customize-rendering&#34;&gt;&lt;div&gt;snippets to customize rendering&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippets-to-customize-rendering&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Let&amp;rsquo;s say you&amp;rsquo;re building a Menu component. Each menu item is a &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; with some non-trivial children.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To allow the client of Menu customize how items are rendered, you could provide props for things like colors, padding etc. or you could allow ultimate flexibility by accepting an optional &lt;code&gt;menuitem&lt;/code&gt; prop that is a snippet that renders the item.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You can think of it as a headless UI i.e. you provide the necessary structure and difficult logic like keyboard navigation etc. and allow the client lots of control over how things are rendered.&lt;/div&gt;&#xA;&#xA;&lt;h1 class=&#34;hdr-with-anchor&#34; id=&#34;snippets-for-library-of-icons&#34;&gt;&lt;div&gt;snippets for library of icons&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#snippets-for-library-of-icons&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h1&gt;&#xA;&#xA;&lt;div&gt;Before snippets every SVG Icon I used was a Svelte component. Many icons means many files.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Now I have a single &lt;code&gt;Icons.svelte&lt;/code&gt; file, like:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt; &lt;span class=&#34;na&#34;&gt;module&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kr&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;IconMenu&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;IconSettings&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;};&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;script&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{#snippet IconMenu(arg1, arg2, ...)}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;svg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;... icon svg&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;svg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{/snippet}}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{#snippet IconSettings()}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;svg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;... icon svg&lt;span class=&#34;p&#34;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;svg&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;&amp;gt;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;{/snippet}}&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
  <entry>
   <title>C++ engineering decision in SumatraPDF code</title>
   <link href="https://blog.kowalczyk.info/a-xf4h/c-engineering-decision-in-sumatrapdf-code.html" rel="alternate"></link>
   <updated>2025-07-02T00:00:00Z</updated>
   <id>tag:blog.kowalczyk.info,2025-07-02:/a-xf4h/c-engineering-decision-in-sumatrapdf-code.html</id>
   <content type="html">&lt;div class=&#34;notion-page&#34; id=&#34;xf4h&#34;&gt;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://www.sumatrapdfreader.org/free-pdf-reader&#34;&gt;SumatraPDF&lt;/a&gt; is a medium size (120k+ loc, not counting dependencies) Windows GUI (win32) C++ code base started by me and mostly written by 2 people.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The goals of SumatraPDF are to be:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;fast&lt;/li&gt;&#xA;&lt;li&gt;small&lt;/li&gt;&#xA;&lt;li&gt;packed with features&lt;/li&gt;&#xA;&lt;li&gt;and yet with thoughtfully minimal UI&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s not just a matter of pride in craftsmanship of writing code. I believe being fast and small are a big reason for SumatraPDF&amp;rsquo;s success. People notice when an app starts in an instant because that&amp;rsquo;s sadly not the norm in modern software.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The engineering goals of SumatraPDF are:&lt;/div&gt;&#xA;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;reliable (no crashes)&lt;/li&gt;&#xA;&lt;li&gt;fast compilation to enable fast iteration&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&#xA;&lt;div&gt;SumatraPDF has been successful achieving those objectives so I&amp;rsquo;m writing up my C++ implementation decisions.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I know those decisions are controversial. Maybe not Terry Davis level of controversial but still.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You probably won&amp;rsquo;t adopt them. Even if you wanted to, you probably couldn&amp;rsquo;t. There&amp;rsquo;s no way code like this would pass Google review. Not because it&amp;rsquo;s bad but because it&amp;rsquo;s different.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Diverging from mainstream this much is only feasible if you have total control: it&amp;rsquo;s your company or your own open-source project.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;If my ideas were just like everyone else&amp;rsquo;s ideas, there would be little point in writing about them, would it?&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;use-utf8-strings-internally&#34;&gt;&lt;div&gt;Use UTF8 strings internally&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#use-utf8-strings-internally&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;My app only runs on Windows and a string native to Windows is &lt;code&gt;WCHAR*&lt;/code&gt; where each character consumes 2 bytes.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Despite that I mostly use &lt;code&gt;char*&lt;/code&gt; assumed to be utf8-encoded.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I only decided on that after lots of code was written so it was a refactoring odyssey that is still ongoing.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;My initial impetus was to be able to compile non-GUI parts under Linux and Mac. I abandoned that goal but I think that&amp;rsquo;s a good idea anyway.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;code&gt;WCHAR*&lt;/code&gt; strings are 2x larger than &lt;code&gt;char*&lt;/code&gt;. That&amp;rsquo;s more memory used which also makes the app slower.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Binaries are bigger if string constants are &lt;code&gt;WCHAR*&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The implementation rule is simple: I only convert to &lt;code&gt;WCHAR*&lt;/code&gt; when calling Windows API. When Windows API returns &lt;code&gt;WCHA*&lt;/code&gt; I convert it to utf-8.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;no-exceptions&#34;&gt;&lt;div&gt;No exceptions&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#no-exceptions&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Do you want to hear a joke? &amp;ldquo;Zero-cost exceptions&amp;rdquo;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Throwing and catching exceptions generate bloated code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Exceptions are a non-local control flow that makes it hard to reason about program. Every memory allocation becomes a potential leak.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;But RAII, you protest. RAII is a &amp;ldquo;solution&amp;rdquo; to a problem created by exceptions. How about I don&amp;rsquo;t create the problem in the first place.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;hard-core-include-discipline&#34;&gt;&lt;div&gt;Hard core #include discipline&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#hard-core-include-discipline&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;I &lt;a href=&#34;/article/qg/order-of-include-headers-in-cc.html&#34;&gt;wrote about it in depth&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;my-objects-are-not-shy&#34;&gt;&lt;div&gt;My objects are not shy&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#my-objects-are-not-shy&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;I don&amp;rsquo;t bother with &lt;code&gt;private&lt;/code&gt; and &lt;code&gt;protected&lt;/code&gt;. &lt;code&gt;struct&lt;/code&gt; is just &lt;code&gt;class&lt;/code&gt; with guts exposed by default, so I use that.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;While intellectually I understand the reasoning behind hiding implementation details in practices it becomes busy work of typing noise and then even more typing when you change your mind about visibility.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;m the only person working on the code so I don&amp;rsquo;t need to force those of lesser intellect to write the code properly.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;my-objects-are-shy&#34;&gt;&lt;div&gt;My objects are shy&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#my-objects-are-shy&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;At the same time I minimize what goes into a class, especially methods.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The smaller the class, the faster the build.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;A common problem is adding too many methods to a class.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You have a &lt;code&gt;StrVec&lt;/code&gt; class for array of strings. A lesser programmer is tempted to add &lt;code&gt;Join(const char* sep)&lt;/code&gt; method to &lt;code&gt;StrVec&lt;/code&gt;. A wise programmer makes it a stand-alone function: &lt;code&gt;Join(const StrVec&amp;amp; v, const char* sep)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This is enabled by making everything in a class public. If you limit visibility you then have to use &lt;code&gt;friend&lt;/code&gt;to allow &lt;code&gt;Join()&lt;/code&gt; function access what it needs. Another example of &amp;ldquo;solution&amp;rdquo; to self-inflicted problems.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;minimize-ifdef&#34;&gt;&lt;div&gt;Minimize #ifdef&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#minimize-ifdef&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;code&gt;#ifdef&lt;/code&gt; is problematic because it creates code paths that I don&amp;rsquo;t always build.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I provide arm64, intel 32-bit and 64-bit builds but typically only develop with 64-bit intel build. Every &lt;code&gt;#ifdef&lt;/code&gt; that branches on architecture introduces potential for compilation error which I&amp;rsquo;ll only know about when my daily ci build fails.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Consider 2 possible implementations of &lt;code&gt;IsProcess64Bit()&lt;/code&gt;:&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;strong&gt;Bad&lt;/strong&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;IsProcess64Bit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#ifdef _WIN64&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#else&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;false&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;#endif&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;&lt;strong&gt;Good&lt;/strong&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;IsProcess64Bit&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;sizeof&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;uintptr_t&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;The bad version has a bug: it was correct when I was only doing intel builds but became buggy when I added arm64 builds.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;This conflicts with the goal of smallest possible size but it&amp;rsquo;s worth it.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;stress-testing&#34;&gt;&lt;div&gt;Stress testing&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#stress-testing&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;SumatraPDF supports a lot of very complex document and image formats.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Complex format require complex code that is likely to have bugs.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I also have lots of files in those formats.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;ve added stress testing functionality where I point SumatraPDF to a folder with files and tell it to render all of them.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For greater coverage, I also simulate some of the possible UI actions users can take like searching, switching view modes etc.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;crash-reporting&#34;&gt;&lt;div&gt;Crash reporting&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#crash-reporting&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;I &lt;a href=&#34;/article/c4qb/how-to-make-software-crash-less.html&#34;&gt;wrote about it in depth&lt;/a&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;heavy-use-of-crashif&#34;&gt;&lt;div&gt;Heavy use of CrashIf()&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#heavy-use-of-crashif&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;C/C++ programmers are familiar with &lt;code&gt;assert()&lt;/code&gt; macro.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;code&gt;CrashIf()&lt;/code&gt; is my version of that, tailored to my needs.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The purpose of &lt;code&gt;assert&lt;/code&gt; / &lt;code&gt;CrashIf&lt;/code&gt; is to add checks to detect incorrect use of APIs or invalid states in the program.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;For example, if the code tries to access an element of an array at an invalid index (negative or larger than size of the array), it indicates a bug in the program.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I want to be notified about such bugs both when I test SumatraPDF and when it runs on user&amp;rsquo;s computers.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;As the name implies, it&amp;rsquo;ll crash (by de-referencing null pointer) and therefore generate a crash report.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s enabled in debug and pre-release builds but not in release builds. Release builds have many, many users so I worry about too many crash reports.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;premake-to-generate-visual-studio-solution&#34;&gt;&lt;div&gt;premake to generate Visual Studio solution&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#premake-to-generate-visual-studio-solution&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Visual Studio uses XML files as a list of files in the project and build format. The format is impossible to work with in a text editor so you have no choice but to use Visual Studio to edit the project / solution.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To add a new file: find the right UI element, click here, click there, pick a file using file picker, click again.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;To change a compilation setting of a project or a file? Find the right UI element, click here, click there, type this, confirm that.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;You accidentally changed compilation settings of 1 file out of a hundred? Good luck figuring out which one. Go over all files in UI one by one.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In other words: managing project files using Visual Studio UI is a nightmare.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://premake.github.io/&#34;&gt;Premake&lt;/a&gt; is a solution. It&amp;rsquo;s a meta-build system. You define your build using lua scripts, which look like test configuration files.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Premake then can generate Visual Studio projects, XCode project, makefiles etc. That&amp;rsquo;s the &lt;code&gt;meta&lt;/code&gt; part.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It was truly a life saver on project with lots of files (SumatraPDF&amp;rsquo;s own are over 300, many times more for third party libraries).&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;using-analyze-and-cppcheck&#34;&gt;&lt;div&gt;Using /analyze and cppcheck&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#using-analyze-and-cppcheck&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://cppcheck.sourceforge.io/&#34;&gt;cppcheck&lt;/a&gt; and &lt;code&gt;/analyze&lt;/code&gt; flag in &lt;code&gt;cl.exe&lt;/code&gt; are tools to find bugs in C++ code via static analysis. They are like a C++ compiler but instead of generating code, they analyze control flow in a program to find potential programs.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;It&amp;rsquo;s a cheap way to find some bugs, so there&amp;rsquo;s no excuse to not run them from time to time on your code.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;using-asan-builds&#34;&gt;&lt;div&gt;Using asan builds&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#using-asan-builds&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;&lt;a target=&#34;_blank&#34; href=&#34;https://learn.microsoft.com/en-us/cpp/sanitizers/asan?view=msvc-170&#34;&gt;Address Sanitizer&lt;/a&gt; (&lt;code&gt;asan&lt;/code&gt;) is a compiler flag &lt;code&gt;/fsanitize=address&lt;/code&gt; that instruments the code with checks for common memory-related bugs like using an object after freeing it, over-writing values on the stack, freeing an object twice, writing past allocated memory.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The downside of this instrumentation is that the code is much slower due to overhead of instrumentation.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;ve created a project for release build with asan and run it occasionally, especially in stress test.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;write-for-the-debugger&#34;&gt;&lt;div&gt;Write for the debugger&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#write-for-the-debugger&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;Programmers love to code golf i.e. put us much code on one line as possible. As if lines of code were expensive.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Many would write:&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;strong&gt;Bad&lt;/strong&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;I write:&lt;/div&gt;&#xA;&#xA;&lt;div&gt;&lt;strong&gt;Good&lt;/strong&gt;:&lt;/div&gt;&#xA;&lt;pre class=&#34;chroma light&#34;&gt;&lt;code&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;c1&#34;&gt;// ...&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;char&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;*&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;start&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;offset&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;);&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&#xA;&lt;div&gt;Why?&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Imagine you&amp;rsquo;re in a debugger stepping through a debug build of your code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The second version makes it trivial to set a breakpoint at &lt;code&gt;return s&lt;/code&gt; line and look at the value of &lt;code&gt;s&lt;/code&gt;. The first doesn&amp;rsquo;t.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I don&amp;rsquo;t optimize for smallest number of lines of code but for how easy it is to inspect the state of the program in the debugger.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;In practice it means that I intentionally create intermediary variables like &lt;code&gt;s&lt;/code&gt; in the example above.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;do-it-yourself-standard-library&#34;&gt;&lt;div&gt;Do it yourself standard library&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#do-it-yourself-standard-library&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;I&amp;rsquo;m not using STL. Yes, I wrote my own string and vector class. There are several reasons for that.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;historical-reason&#34;&gt;&lt;div&gt;Historical reason&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#historical-reason&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;When I started SumatraPDF over 15 years ago STL was crappy.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;bad-apis&#34;&gt;&lt;div&gt;Bad APIs&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#bad-apis&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;Today STL is still crappy. STL implementations improved greatly but the APIs still suck.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;There&amp;rsquo;s no API to insert something in the middle of a string or a vector. I understand the intent of separation of data structures and algorithms but I&amp;rsquo;m a pragmatist and to my pragmatist eyes &lt;code&gt;v.insert (v.begin(), myarray, myarray+3);&lt;/code&gt; is just stupid compared to &lt;code&gt;v.inert(3, el)&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;code-bloat&#34;&gt;&lt;div&gt;Code bloat&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#code-bloat&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;STL is bloated. Heavy use of templates leads to lots of generated code i.e. surprisingly large binaries for supposedly low-level language.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;That bloat is invisible i.e. you won&amp;rsquo;t know unless you inspect generated binaries, which no one does.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;The bloat is out of my control. Even if I notice, I can&amp;rsquo;t fix STL classes. All I can do is to write my non-bloaty alternative, which is what I did.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;slow-compilation-times&#34;&gt;&lt;div&gt;Slow compilation times&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#slow-compilation-times&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;Compilation of C code is not fast but it feels zippy compared to compilation of C++ code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Heavy use of templates is big part of it. STL implementations are over-templetized and need to provide all the C++ support code (operators, iterators etc.).&lt;/div&gt;&#xA;&#xA;&lt;div&gt;As a pragmatist, I only implement the absolute minimum functionality I use in my code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I minimize use of templates. For example &lt;code&gt;Str&lt;/code&gt; and &lt;code&gt;WStr&lt;/code&gt; could be a single template but are 2 implementations.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;i-don-t-understand-c&#34;&gt;&lt;div&gt;I don&amp;rsquo;t understand C++&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#i-don-t-understand-c&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;I understand the subset of C++ I use but the whole of C++ is impossibly complicated. For example I&amp;rsquo;ve read a bunch about &lt;code&gt;std::move()&lt;/code&gt; and I&amp;rsquo;m not confident I know how to use it correctly and that&amp;rsquo;s just one of many complicated things in C++.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;C++ is too subtle and I don&amp;rsquo;t want my code to be a puzzle.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;possibility-of-optimized-implementations&#34;&gt;&lt;div&gt;Possibility of optimized implementations&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#possibility-of-optimized-implementations&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;I wrote a &lt;code&gt;StrVec&lt;/code&gt; class that is optimized for storing vector of strings. It&amp;rsquo;s more efficient than &lt;code&gt;std::vector&amp;lt;std::string&amp;gt;&lt;/code&gt; by a large margin and I use it extensively.&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;hdr-with-anchor&#34; id=&#34;temporary-allocator-and-pool-allocators&#34;&gt;&lt;div&gt;Temporary allocator and pool allocators&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#temporary-allocator-and-pool-allocators&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h3&gt;&#xA;&#xA;&lt;div&gt;I use temporary allocators heavily. They make the code faster and smaller.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Technically STL has support for non-standard allocators but the API is so bad that I would rather not.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;My temporary allocator and pool allocators are very small and simple and I can add support for them only when beneficial.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;minimize-unsigned-int&#34;&gt;&lt;div&gt;Minimize unsigned int&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#minimize-unsigned-int&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;STL and standard C library like to use &lt;code&gt;size_t&lt;/code&gt; and other unsigned integers.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I think it was a mistake. Go shows that you can just use &lt;code&gt;int&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Having two types leads to cast-apalooza. I don&amp;rsquo;t like visual noise in my code.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Unsigned are also more dangerous. When you substract you can end up with a bigger value. Indexing from end is subtle, &lt;code&gt;for (int i = n; i &amp;gt;= 0; i--)&lt;/code&gt; is buggy because &lt;code&gt;i &amp;gt;= 0&lt;/code&gt; is always true for unsigned.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;Sadly I only realized this recently so there&amp;rsquo;s a lot of code still to refactor to change use of &lt;code&gt;size_t&lt;/code&gt; to &lt;code&gt;int&lt;/code&gt;.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;mostly-raw-pointers&#34;&gt;&lt;div&gt;Mostly raw pointers&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#mostly-raw-pointers&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;No &lt;code&gt;std::unique_ptr&lt;/code&gt; for me.&lt;/div&gt;&#xA;&#xA;&lt;h2 class=&#34;hdr-with-anchor&#34; id=&#34;warnings-are-errors&#34;&gt;&lt;div&gt;Warnings are errors&lt;/div&gt;&lt;a class=&#34;header-anchor&#34; href=&#34;#warnings-are-errors&#34;&gt;&#xA;&lt;svg xmlns=&#34;http://www.w3.org/2000/svg&#34; width=&#34;1em&#34; height=&#34;1em&#34; viewBox=&#34;0 0 24 24&#34; fill=&#34;none&#34;&#xA;&#x9;stroke=&#34;currentColor&#34; stroke-width=&#34;2&#34; stroke-linecap=&#34;round&#34; stroke-linejoin=&#34;round&#34;&#xA;&#x9;class=&#34;header-anchor-widget-icon&#34;&gt;&#xA;&#x9;&lt;path d=&#34;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&#34;&gt;&lt;/path&gt;&#xA;&#x9;&lt;path d=&#34;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&#34;&gt;&lt;/path&gt;&#xA;&lt;/svg&gt;&#xA;&lt;/a&gt;&#xA;&lt;/h2&gt;&#xA;&#xA;&lt;div&gt;C++ makes a distinction between compilation errors and compilation warnings.&lt;/div&gt;&#xA;&#xA;&lt;div&gt;I don&amp;rsquo;t like sloppy code and polluting build output with warning messages so for my own code I use a compiler flag that turns warnings into errors, which forces me to fix the warnings.&lt;/div&gt;&#xA;&#xA;&lt;/div&gt;&#xA;</content>
  </entry>
 </feed>