<rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Hacker News Personal Blogs 2018 | Top 100 Blogs</title><link>https://hn-blogs.kronis.dev/feed-top100.xml</link><description>A collection of blog posts from users of Hacker News, based on RSS feeds.</description><language>en-US</language><lastBuildDate>Sat, 07 Mar 2026 15:11:22 GMT</lastBuildDate><generator>rfeed v1.1.1</generator><docs>https://github.com/svpino/rfeed/blob/master/README.md</docs><item><title>Turning the Static Dynamic with Gatsby + Netlify Functions + Netlify Identity</title><link>https://www.swyx.io/gatsby-static-dynamic</link><description>&lt;p&gt;Gatsby is great for not only static sites but also traditional web applications. You can add authentication and serverless functionality and get up and running incredibly quickly with Netlify - here's how.&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 26 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/gatsby-static-dynamic</guid></item><item><title>Nethack Deaths</title><link>https://rjp.is/blogging/posts/2018/12/nethack-deaths/</link><description>In which we clean up a messy data set to make more sense of it.</description><author>infrequent oscillations</author><pubDate>Sun, 23 Dec 2018 11:48:44 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/2018/12/nethack-deaths/</guid></item><item><title>Running latest kernels on ARM Scaleway servers</title><link>https://anisse.astier.eu/distro-kernel-scaleway-arm.html</link><description>&lt;p&gt;Scaleway, a french cloud provider, has been renting baremetal ARM servers for a few years now, and virtual ARM64 servers more recently. They ship with a scaleway-provided kernel and initird, which isn't updated as often as I'd like. The latest ARMv7 (32 bits) kernel, is 4.9.93, while the …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Fri, 21 Dec 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/distro-kernel-scaleway-arm.html</guid></item><item><title>New Zealand Otago Trip in a 2019 Mustang GT</title><link>https://smcleod.net/2018/12/new-zealand-otago-trip-in-a-2019-mustang-gt/</link><description>&lt;!-- TODO: add mapbox --&gt;
&lt;p&gt;In late November of 2018 I was lucky enough to get my hands on the upcoming 2019 Sport spec Mustang GT v8 to be its first driver.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not usually an American Muscle enthusiast, but the new 2019 GT really is quite different from its slightly older counterparts,
with a new specially developed &lt;a href="https://www.caranddriver.com/reviews/a24847025/2018-ford-mustang-automatic-transmission-performance/"&gt;10 speed gearbox&lt;/a&gt;
(yes, &lt;em&gt;10&lt;/em&gt; gears - because more is better right?), tuned up suspension and so seemed like it would make for a pretty fun trip.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Thu, 20 Dec 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/12/new-zealand-otago-trip-in-a-2019-mustang-gt/</guid></item><item><title>Perfect Advent Calendars</title><link>https://rjp.is/blogging/posts/2018/12/perfect-advent-calendars/</link><description>In which we make things symmetrical by brute force.</description><author>infrequent oscillations</author><pubDate>Tue, 18 Dec 2018 07:56:32 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/2018/12/perfect-advent-calendars/</guid></item><item><title>Interesting queries on a football database</title><link>https://rjp.is/blogging/posts/football_database/</link><description>In which we query a football database for facts and fun.</description><author>infrequent oscillations</author><pubDate>Mon, 17 Dec 2018 15:53:00 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/football_database/</guid></item><item><title>XCat 1.0 released or: XPath injection issues are severely underrated</title><link>https://tomforb.es/blog/xcat-10/</link><description>I’ve just released xcat 1.0 and it’s demonstration application after like 5 years of on-off development. Feels good! The genesis of xcat was when my boss, Sid, walked up to me out of the blue and asked if I wanted to go on an all expenses paid trip to Amsterdam. Who the hell wouldn’t say yes to that...</description><author>Tom Forbes</author><pubDate>Sun, 09 Dec 2018 21:58:01 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/xcat-10/</guid></item><item><title>Bitlbee to Pleroma</title><link>https://rjp.is/blogging/posts/bitlbee-to-pleroma/</link><description>In which we talk to Pleroma through Bitlbee.</description><author>infrequent oscillations</author><pubDate>Wed, 05 Dec 2018 17:50:36 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/bitlbee-to-pleroma/</guid></item><item><title>Invited to join the Django software foundation</title><link>https://tomforb.es/blog/dsf-member/</link><description>A few days ago I was invited to become a member of the Django software foundation due to my contributions to Django. Awesome! Now I get to hang about in the super-secret mailing list and discuss django-related illuminati business. Removal of core developers The hot news in Django-land is the proposa...</description><author>Tom Forbes</author><pubDate>Sun, 02 Dec 2018 21:58:01 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/dsf-member/</guid></item><item><title>Expert Excuses for Not Writing Unit Tests</title><link>https://boyter.org/posts/expert-excuses-for-not-writing-unit-tests/</link><description>&lt;p&gt;A while back I collected all of the fake Orly book covers I could find an posted them online &lt;a href="https://boyter.org/2016/04/collection-orly-book-covers/"&gt;https://boyter.org/2016/04/collection-orly-book-covers/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I also mentioned that I was seriously considering writing content for the &amp;ldquo;Expert Excuses for Not Writing Unit Tests&amp;rdquo; one. I think I had this idea at the time that it was something I could potentially sell or use to raise my profile. Since I am not a comedy writer there is a market of about 0 people in the universe who would pay for content like this. I have no idea what I was thinking.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 27 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/expert-excuses-for-not-writing-unit-tests/</guid></item><item><title>How to get Google Home / Google Assistant to call your iOS iPhone</title><link>http://blog.pythonaro.com/2018/11/how-to-get-google-home-google-assistant.html</link><description>If you have an iPhone, Google Assistant and Google Home won't be able to call or ring your phone out of the box, since it's an Android-only feature. If you are not in the US, you cannot even use the workaround of calling your number. So what can you do, if you tend to misplace your phone around the house ? (ahem)&lt;br /&gt;
&lt;ol&gt;
&lt;li&gt;Get an account on &lt;a href="https://ifttt.com/"&gt;IFTTT&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Install the &lt;a href="https://itunes.apple.com/us/app/ifttt/id660944635"&gt;IFTTT app&lt;/a&gt; on your phone&lt;/li&gt;
&lt;li&gt;create a new applet, click on "&lt;i&gt;this&lt;/i&gt;" and select &lt;i&gt;&lt;b&gt;Google Assistant&lt;/b&gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;select "&lt;i&gt;say a simple phrase&lt;/i&gt;"&amp;nbsp; and enter the details you prefer (e.g. "make a noise on my phone" or "ping my phone". Note the most common "ring my phone" or "where is my phone" are reserved by Google and won't work).&lt;/li&gt;
&lt;li&gt;click on "&lt;i&gt;then&lt;/i&gt;" and select &lt;i&gt;&lt;b&gt;VoIP Calls&lt;/b&gt;&lt;/i&gt;&lt;/li&gt;
&lt;li&gt;enter a message the phone will tell you if you pick up (e.g. "Glad you found me!")&lt;/li&gt;
&lt;li&gt;Save the applet.&lt;/li&gt;
&lt;/ol&gt;
Now, when you say that phrase to Google Home / Goole Assistant, it will ring your phone, so you can dig it out of the sofa or the Lego box (ahem).</description><author>Subclassed</author><pubDate>Mon, 26 Nov 2018 16:41:57 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/11/how-to-get-google-home-google-assistant.html</guid></item><item><title>Networking Essentials: Network Security</title><link>https://www.swyx.io/networking-essentials-network-security-1fcp</link><description>&lt;p&gt;What is Traffic Engineering?&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 25 Nov 2018 03:43:21 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-network-security-1fcp</guid></item><item><title>Types of Development</title><link>https://boyter.org/posts/types-of-development/</link><description>&lt;h3 id="types-of-development-1"&gt;Types of Development #1&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Rage driven development&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Where an existing application/process causes one to rage so hard you spend the next 6 weeks over-engineering a solution to solve a simple problem. Example Perl.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3 id="types-of-development-2"&gt;Types of Development #2&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Test driven development&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Where previous projects and death marches result in a violent reaction of over-correcting for past failures and everything must be tested dammit. Example includes any project where the goal is 100% test coverage.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Sun, 25 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/types-of-development/</guid></item><item><title>Breaking the Ice for Underwater Hockey</title><link>https://svedic.org/personal/underwater-hockey</link><description>&amp;#8220;This is for you kid,&amp;#8221; said my uncle, &amp;#8220;have fun!&amp;#8221; I was 12 and I got my first mask and fins. I loved it. I would go every day to the seaside, to the rocky pier, and dive next to &amp;#8230; &lt;a href="https://svedic.org/personal/underwater-hockey"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Svedic.org</author><pubDate>Thu, 22 Nov 2018 11:11:08 GMT</pubDate><guid isPermaLink="true">https://svedic.org/personal/underwater-hockey</guid></item><item><title>Writing a lisp compiler from scratch in JavaScript: 1. lisp to assembly</title><link>http://notes.eatonphil.com/compiler-basics-lisp-to-assembly.html</link><description>&lt;p class="note"&gt;
  Next in compiler basics:
  &amp;lt;! forgive me, for I have sinned &gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-functions.html"&gt;2. user-defined functions and variables&lt;/a&gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-llvm.html"&gt;3. LLVM&lt;/a&gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-llvm-conditionals.html"&gt;4. LLVM conditionals and compiling fibonacci&lt;/a&gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-llvm-system-calls.html"&gt;5. LLVM system calls&lt;/a&gt;
  &lt;br /&gt;
  &lt;a href="/compiler-basics-an-x86-upgrade.html"&gt;6. an x86 upgrade&lt;/a&gt;
&lt;/p&gt;&lt;p&gt;In this post we'll write a simple compiler in Javascript (on Node)
without any third-party libraries. Our goal is to take an input
program like &lt;code&gt;(+ 1 (+ 2 3))&lt;/code&gt; and produce an output assembly program
that does these operations to produce &lt;code&gt;6&lt;/code&gt; as the exit code. The
resulting compiler can be found
&lt;a href="https://github.com/eatonphil/ulisp"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We'll cover:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parsing&lt;/li&gt;
&lt;li&gt;Code generation&lt;/li&gt;
&lt;li&gt;Assembly basics&lt;/li&gt;
&lt;li&gt;Syscalls&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And for now we'll omit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Programmable function definitions&lt;/li&gt;
&lt;li&gt;Non-symbol/-numeric data types&lt;/li&gt;
&lt;li&gt;More than 3 function arguments&lt;/li&gt;
&lt;li&gt;Lots of safety&lt;/li&gt;
&lt;li&gt;Lots of error messsages&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="parsing"&gt;Parsing&lt;/h3&gt;&lt;p&gt;We pick the &lt;a href="https://en.wikipedia.org/wiki/S-expression"&gt;S-expression&lt;/a&gt;
syntax mentioned earlier because it's very easy to parse. Furthermore,
our input language is so limited that we won't even break our parser
into separate lexing/parsing stages.&lt;/p&gt;
&lt;p class="note"&gt;
  Once you need to support string literals, comments, decimal
  literals, and other more complex literals it becomes easier to use
  separate stages.

  &lt;br /&gt;
  &lt;br /&gt;

  If you're curious about these separate stages of parsing, you may be
  interested in my post
  on &lt;a href="http://notes.eatonphil.com/writing-a-simple-json-parser.html"&gt;writing
  a JSON parser&lt;/a&gt;.

  &lt;br /&gt;
  &lt;br /&gt;

  Or, check out my BSDScheme project for a fully-featured
  &lt;a href="https://github.com/eatonphil/bsdscheme/blob/master/src/lex.d"&gt;lexer&lt;/a&gt;
  and
  &lt;a href="https://github.com/eatonphil/bsdscheme/blob/master/src/parse.d"&gt;parser&lt;/a&gt;
  for Scheme.
&lt;/p&gt;&lt;p&gt;The parser should produce an Abstract Syntax Tree (AST), a data
structure representing the input program. Specifically, we want &lt;code&gt;(+ 1 (+ 2 3))&lt;/code&gt;
to produce &lt;code&gt;['+', 1, ['+', 2, 3]]&lt;/code&gt; in Javascript.&lt;/p&gt;
&lt;p&gt;There are many different ways to go about parsing but the most
intuitive to me is to have a function that accepts a program (a
string) and returns a tuple containing the program parsed so far (an
AST) and the rest of the program (a string) that hasn't been
parsed.&lt;/p&gt;
&lt;p&gt;That leaves us with a function skeleton that looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;logic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;added&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The code that initially calls parse will thus have to deal with
unwrapping the outermost tuple to get to the AST. For a more helpful
compiler we could check that the entire program &lt;em&gt;was&lt;/em&gt; actually parsed
by failing if the second element of the return result is not the empty
string.&lt;/p&gt;
&lt;p&gt;Within the function we will iterate over each character and accumulate
until we hit space, left or right parenthesis:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'('&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// TODO&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;')'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// TODO&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The recursive parts are always the most challenging. The right paren
is easiest. We must push the current token and return all tokens with
the rest of the program:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'('&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// TODO&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;')'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Finally the left paren should recurse, add the parsed tokens to the
list of sibling tokens, and force the loop to start at the new
unparsed point.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;charAt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'('&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;parsed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;')'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;substring&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;currentToken&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;char&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Assuming this is all in &lt;code&gt;parser.js&lt;/code&gt;, let's try it out in the REPL:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;node
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;const&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;parse&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./parser'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
undefined
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;console.log&lt;span class="o"&gt;(&lt;/span&gt;JSON.stringify&lt;span class="o"&gt;(&lt;/span&gt;parse&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'(+ 3 (+ 1 2)'&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;[[[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;+&amp;quot;&lt;/span&gt;,3,&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;+&amp;quot;&lt;/span&gt;,1,2&lt;span class="o"&gt;]]]&lt;/span&gt;,&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Solid. We move on.&lt;/p&gt;
&lt;h3 id="assembly-101"&gt;Assembly 101&lt;/h3&gt;&lt;p&gt;Assembly is essentially the lowest-level programming language we can
use. It is a human readable, 1:1 representation of the binary
instructions the CPU can interpret. Conversion from assembly to
binary is done with an assembler; the reverse step is done with a
disassembler. We'll use &lt;code&gt;gcc&lt;/code&gt; for assembling since it deals with some
&lt;a href="http://fabiensanglard.net/macosxassembly/index.php"&gt;oddities&lt;/a&gt; of
assembly programming on macOS.&lt;/p&gt;
&lt;p&gt;The primary data structures in assembly are registers (temporary
variables stored by the CPU) and the program stack. Every function in
a program has access to the same registers, but convention cordons
off sections of the stack for each function so it ends up being a
slightly more durable store than registers. &lt;code&gt;RAX&lt;/code&gt;, &lt;code&gt;RDI&lt;/code&gt;, &lt;code&gt;RDX&lt;/code&gt;, and
&lt;code&gt;RSI&lt;/code&gt; are a few registers available to us.&lt;/p&gt;
&lt;p&gt;Now we only need to know a few instructions to compile our program
(the rest of programming assembly is convention):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MOV&lt;/code&gt;: store one register's content into another, or store a literal number into a register&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ADD&lt;/code&gt;: store the sum of two register's contents in the first register&lt;/li&gt;
&lt;li&gt;&lt;code&gt;PUSH&lt;/code&gt;: store a register's content on the stack&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POP&lt;/code&gt;: remove the top-most value from the stack and store in a register&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CALL&lt;/code&gt;: enter a new section of the stack and start running the function&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RET&lt;/code&gt;: enter the calling functions stack and return to evaluating from the next instruction after the call&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SYSCALL&lt;/code&gt;: like &lt;code&gt;CALL&lt;/code&gt; but where the function is handled by the kernel&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="function-calling-convention"&gt;Function calling convention&lt;/h3&gt;&lt;p&gt;Assembly instructions are flexible enough that there is no
language-defined way to make function calls. Therefore it is important
to answer (at least) the following few questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Where are parameters stored by the caller so that the callee has access to them?&lt;/li&gt;
&lt;li&gt;Where is the return value stored by the callee so the caller has access to it?&lt;/li&gt;
&lt;li&gt;What registers are saved by whom?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Without getting too far into the specifics, we'll assume the following
answers for development on x86_64 macOS and Linux systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parameters are stored (in order) in the &lt;code&gt;RDI&lt;/code&gt;, &lt;code&gt;RSI&lt;/code&gt;, and &lt;code&gt;RDX&lt;/code&gt; registers&lt;ul&gt;
&lt;li&gt;We won't support passing more than three arguments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The return value is stored in the &lt;code&gt;RAX&lt;/code&gt; register&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RDI&lt;/code&gt;, &lt;code&gt;RSI&lt;/code&gt;, and &lt;code&gt;RDX&lt;/code&gt; registers are stored by the caller&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="code-generation"&gt;Code generation&lt;/h3&gt;&lt;p&gt;With assembly basics and the function call convention in mind, we've
got enough to generate code from the parsed program's AST.&lt;/p&gt;
&lt;p&gt;The skeleton of our compile code will look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;depth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;indent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;depth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'  '&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;indent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;compile_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// If arg AST is a list, call compile_call on it&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Else must be a literal number, store in destination register&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;compile_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Save param registers to the stack&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Compile arguments and store in param registers&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Call function&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Restore param registers from the stack&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Move result into destination if provided&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;emit_prefix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Assembly prefix&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;emit_postfix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Assembly postfix&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit_prefix&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;compile_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit_postfix&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From our pseudo-code in comments it is simple enough to fill in.
Let's fill in everything but the prefix and postfix code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;compile_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// If arg AST is a list, call compile_call on it&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;compile_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Else must be a literal number, store in destination register&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`MOV &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;, &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;BUILTIN_FUNCTIONS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'+'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'plus'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PARAM_REGISTERS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'RDI'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'RSI'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'RDX'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;compile_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Save param registers to the stack&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`PUSH &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PARAM_REGISTERS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Compile arguments and store in param registers&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;compile_argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PARAM_REGISTERS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Call function&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`CALL &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;BUILTIN_FUNCTIONS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fun&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fun&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Restore param registers from the stack&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`POP &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;PARAM_REGISTERS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// Move result into destination if provided&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`MOV &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;, RAX`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// For nice formatting&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In a better compiler, we would not make &lt;code&gt;plus&lt;/code&gt; a built-in
function. We'd emit code for the assembly instruction &lt;code&gt;ADD&lt;/code&gt;. However,
making &lt;code&gt;plus&lt;/code&gt; a function makes code generation simpler and also allows
us to see what function calls look like.&lt;/p&gt;
&lt;p&gt;We'll define the &lt;code&gt;plus&lt;/code&gt; built-in function in the prefix code.&lt;/p&gt;
&lt;h3 id="the-prefix"&gt;The prefix&lt;/h3&gt;&lt;p&gt;Assembly programs consist of a few "sections" in memory. The most
important of which are the &lt;code&gt;text&lt;/code&gt; and &lt;code&gt;data&lt;/code&gt; sections. &lt;code&gt;text&lt;/code&gt; is a
read-only section where the program instructions themselves are
stored. The CPU is instructed to start interpreting from some location
in this text section and it will increment through instructions,
evaluating each instruction until it reaches an instruction that tells
it to jump to a different location to evaluate instructions (e.g. with
CALL, RET, or JMP).&lt;/p&gt;
&lt;p&gt;To denote the text section we emit &lt;code&gt;.text&lt;/code&gt; in our prefix before we
emit our generated code.&lt;/p&gt;
&lt;p class="note"&gt;
  The data section is for statically initialized values (e.g. global
  variables). We don't have any need for that right now so we'll
  ignore it.
  &lt;br /&gt;
  &lt;br /&gt;
  &lt;a href="https://www.cs.bgu.ac.il/~caspl122/wiki.files/lab2/ch07lev1sec6/ch07lev1sec6.html"&gt;Here&lt;/a&gt;
  is a good read with more detail on these (and other) sections.
&lt;/p&gt;&lt;p&gt;Additionally, we need to emit an entrypoint (we'll use &lt;code&gt;_main&lt;/code&gt;) and
add a notice (&lt;code&gt;.global _main&lt;/code&gt;) so that the location of this entrypoint
is visible externally. This is important because we let &lt;code&gt;gcc&lt;/code&gt; handle
the hairier parts of generating an executable file and it needs access
to the entrypoint.&lt;/p&gt;
&lt;p&gt;So far, our prefix looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;emit_prefix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'.global _main\n'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'.text\n'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;// TODO: add built-in functions&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'_main:'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The last part of our prefix needs to include the &lt;code&gt;plus&lt;/code&gt; built-in
function. For this, we add the first two parameter registers we agreed
on (&lt;code&gt;RDI&lt;/code&gt; and &lt;code&gt;RSI&lt;/code&gt;) and store the result in &lt;code&gt;RAX&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;emit_prefix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'.global _main\n'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'.text\n'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'plus:'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'ADD RDI, RSI'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'MOV RAX, RDI'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'RET\n'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'_main:'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we're golden.&lt;/p&gt;
&lt;h3 id="the-postfix"&gt;The postfix&lt;/h3&gt;&lt;p&gt;The job of the postfix will be simple, call &lt;code&gt;exit&lt;/code&gt; with the value of
&lt;code&gt;RAX&lt;/code&gt; since this will be the result of the last function called by the
program.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;exit&lt;/code&gt; is a syscall, so we'll use the &lt;code&gt;SYSCALL&lt;/code&gt; instruction to call
it. The x86_64 calling convention on macOS and Linux for &lt;code&gt;SYSCALL&lt;/code&gt;
defines parameters the same way &lt;code&gt;CALL&lt;/code&gt; does. But we also need to tell
&lt;code&gt;SYSCALL&lt;/code&gt; what syscall to call. The convention is to set &lt;code&gt;RAX&lt;/code&gt; to the
integer representing the syscall on the current system. On Linux it
will be &lt;code&gt;60&lt;/code&gt;; on macOS it is &lt;code&gt;0x2000001&lt;/code&gt;.&lt;/p&gt;
&lt;p class="note"&gt;
  When I say "convention", I don't mean that you really have a choice
  as a programmer. It was arbitrary when the operating system and
  standard libraries chose it. But if you want to write a working
  program that uses syscalls or calls out to (say) glibc, you'll need
  to follow these conventions.
&lt;/p&gt;&lt;p&gt;The postfix then looks like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'os'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SYSCALL_MAP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;===&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'darwin'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;'exit'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'0x2000001'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s1"&gt;'exit'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;60&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;emit_postfix&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'MOV RDI, RAX'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Set exit arg&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sb"&gt;`MOV RAX, &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;SYSCALL_MAP&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'exit'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;// Set syscall number&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'SYSCALL'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we're set here too.&lt;/p&gt;
&lt;h3 id="putting-it-all-together"&gt;Putting it all together&lt;/h3&gt;&lt;p&gt;We can finally write our Javascript entrypoint and run our compiler
against a sample program.&lt;/p&gt;
&lt;p&gt;The entrypoint might look like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./parser'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'./compiler'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ast&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we can call it like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nf"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;node&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ulisp.js&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;'(+ 3 (+ 2 1))'&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;.global&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;_main&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;.text&lt;/span&gt;

&lt;span class="nl"&gt;plus:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;ADD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RSI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;RET&lt;/span&gt;

&lt;span class="nl"&gt;_main:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;PUSH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;PUSH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RSI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;PUSH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;PUSH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RSI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RSI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;CALL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;plus&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;POP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RSI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;POP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RSI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RAX&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;CALL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;plus&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;POP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RSI&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;POP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RDI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RAX&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;RAX&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;0x2000001&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nf"&gt;SYSCALL&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="generating-an-executable-file-from-the-output"&gt;Generating an executable file from the output&lt;/h3&gt;&lt;p&gt;If we redirect the previous output to an assembly file and call &lt;code&gt;gcc&lt;/code&gt;
on it, we can generate a program we can run. Then we can echo the &lt;code&gt;$?&lt;/code&gt;
variable to see the exit code of the previous process.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;ulisp.js&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'(+ 3 (+ 2 1))'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;program.S
$&lt;span class="w"&gt; &lt;/span&gt;gcc&lt;span class="w"&gt; &lt;/span&gt;-mstackrealign&lt;span class="w"&gt; &lt;/span&gt;-masm&lt;span class="o"&gt;=&lt;/span&gt;intel&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;program&lt;span class="w"&gt; &lt;/span&gt;program.s
$&lt;span class="w"&gt; &lt;/span&gt;./program
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="m"&gt;6&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And we've got a working compiler! The full source of the compiler is
available &lt;a href="https://github.com/eatonphil/ulisp"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="further-reading"&gt;Further reading&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aaronbloomfield.github.io/pdr/book/x86-64bit-ccc-chapter.pdf"&gt;x86_64 calling convention&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;macOS assembly programming&lt;ul&gt;
&lt;li&gt;&lt;a href="http://fabiensanglard.net/macosxassembly/index.php"&gt;Stack alignment on macOS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://filippo.io/making-system-calls-from-assembly-in-mac-os-x/"&gt;Syscalls on macOS&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Destination-driven code generation&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.cs.indiana.edu/~dyb/pubs/ddcg.pdf"&gt;Kent Dybvig's original paper&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://cs.au.dk/~mis/dOvs/slides/46b-codegeneration-in-V8.pdf"&gt;One-pass code generation in V8&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Finished that intro to compilers post :) lisp to assembly in Javascript &lt;a href="https://t.co/0HDIn4Mv7a"&gt;https://t.co/0HDIn4Mv7a&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/1066863077000441856?ref_src=twsrc%5Etfw"&gt;November 26, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Tue, 20 Nov 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/compiler-basics-lisp-to-assembly.html</guid></item><item><title>Networking Essentials: Traffic Engineering</title><link>https://www.swyx.io/networking-essentials-traffic-engineering-13c4</link><description>&lt;p&gt;What is Traffic Engineering?&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 18 Nov 2018 00:57:56 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-traffic-engineering-13c4</guid></item><item><title>Networking Essentials: Software Defined Networking</title><link>https://www.swyx.io/networking-essentials-software-defined-networking-35n9</link><description>&lt;p&gt;Why Software Defined Networking is taking the networking world by storm&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 04 Nov 2018 23:11:45 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-software-defined-networking-35n9</guid></item><item><title>My New Mac Setup (2018-2020)</title><link>https://www.swyx.io/my-new-mac-setup-4ibi</link><description>&lt;p&gt;quick checklist for setting up a new macbook&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 31 Oct 2018 18:53:20 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/my-new-mac-setup-4ibi</guid></item><item><title>The biggest mistake Postgres ever made</title><link>/2018/10/30/postgres-biggest-mistake/</link><description>&lt;p&gt;Postgres has experienced a long and great run. It is over 20 years old and has a track record of being safe and reliable (which is the top thing I care about in a database). In recent years it has become more cool with things like &lt;a href="https://www.citusdata.com/blog/2016/07/14/choosing-nosql-hstore-json-jsonb/"&gt;JSONB&lt;/a&gt;, &lt;a href="https://www.citusdata.com/blog/2018/09/11/postgresql-11-just-in-time/"&gt;JIT support&lt;/a&gt;, and a powerful &lt;a href="https://www.citusdata.com/blog/2017/10/25/what-it-means-to-be-a-postgresql-extension/"&gt;extension&lt;/a&gt; ecosystem. But, Postgres has made some mistakes along the way, the most notable being the name.&lt;/p&gt;
&lt;p&gt;Postgres gets its name from &lt;a href="https://en.wikipedia.org/wiki/Ingres_(database)"&gt;Ingress&lt;/a&gt;. Ingress was one of the first databases and was lead by Michael Stonebreaker who won a Turing award for Postgres and other works. Ingress began in the early 70s at UC Berkeley, which is still to this day known as a top university when it comes to databases. Out of Ingress came a number of databases you&amp;rsquo;ll still know today such as SQL Server and Sybase. It also as you may have guessed by now spawned Postgres which means Post-Ingress.&lt;/p&gt;
&lt;p&gt;In the early days of Postgres there was no SQL. No not NoSQL, there was not SQL. Postgres had its own query language. It wasn&amp;rsquo;t until 1995 that Postgres received SQL support, and with its addition of SQL support it updated its name to PostgreSQL.&lt;/p&gt;
&lt;p&gt;You see, with Postgres becoming PostgreSQL we began a journey of Postgres being mispronounced for its forseeable future and it is still currently the case. Is it really that big of an issue? Well it&amp;rsquo;s big enough that the PostgreSQL website has a FAQ including &lt;a href="https://www.postgresql.org/about/press/faq/"&gt;&amp;ldquo;How to pronounce PostgreSQL&amp;rdquo;&lt;/a&gt;. As it stands today there are two generally accepted names:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;post-GRES-que-ell&lt;/li&gt;
&lt;li&gt;Postgres&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With one of the above there is far less confusion. And in fact I&amp;rsquo;m not the only one to share this opinion. &lt;a href="https://en.wikipedia.org/wiki/Tom_Lane_(computer_scientist)"&gt;Tom Lane&lt;/a&gt; is a major contributor to every Postgres release for more than the last decade. He&amp;rsquo;s one of the top 10 contributors to open source in general having worked on the JPEG/PNG/TIFF image formats before coming over to database land. Tom has this &lt;a href="https://www.postgresql.org/message-id/2693.1152762174@sss.pgh.pa.us"&gt;classic email&lt;/a&gt; in the PostgreSQL mailing list:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt; [&amp;gt;&amp;gt; Can i get data in postgre from non-postgre db?
&amp;gt; The name is PostgreSQL or Postgres, not postgre.
It might help to explain that the pronunciation is "post-gres" or
"post-gres-cue-ell", not "post-gray-something".
I heard people making this same mistake in presentations at this
past weekend's Postgres Anniversary Conference :-( Arguably,
the 1996 decision to call it PostgreSQL instead of reverting to
plain Postgres was the single worst mistake this project ever made.
It seems far too late to change now, though.
regards, tom lane
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The best part is this was mail was 2006, when it was arguably too late to change the name, and here we are in 2018 with the same issue.&lt;/p&gt;
&lt;p&gt;Personally I may start calling it Postgre just to emphasize a point, but for the rest of you just going with Postgres is probably a safe choice.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Tue, 30 Oct 2018 22:55:56 GMT</pubDate><guid isPermaLink="true">/2018/10/30/postgres-biggest-mistake/</guid></item><item><title>Networking Essentials: Content Distribution</title><link>https://www.swyx.io/networking-essentials-content-distribution-jag</link><description>&lt;p&gt;How CDNs, BitTorrent and Distributed Hash tables work&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Mon, 29 Oct 2018 06:46:33 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-content-distribution-jag</guid></item><item><title>Networking Essentials: Rate Limiting and Traffic Shaping</title><link>https://www.swyx.io/networking-essentials-rate-limiting-and-traffic-shaping-43ii</link><description>&lt;p&gt;How Computer Networks shape, police, measure, and limit the traffic that flow across them.&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 28 Oct 2018 23:19:10 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-rate-limiting-and-traffic-shaping-43ii</guid></item><item><title>Generating Harry Potter Spell Names and Kelewan House Names</title><link>https://boyter.org/posts/generating-harry-potter-spells-and-kelewan-houses/</link><description>&lt;p&gt;Occasionally I try to branch out from working on &lt;a href="https://searchcode.com/"&gt;https://searchcode.com/&lt;/a&gt; &lt;a href="https://searchcodeserver.com/"&gt;https://searchcodeserver.com/&lt;/a&gt; or &lt;a href="https://github.com/boyter/scc"&gt;https://github.com/boyter/scc&lt;/a&gt; and find something that I find interesting to toy around with. Usually I go for something that will only take a few hours to play around with.&lt;/p&gt;
&lt;p&gt;I had recently re-read a book series I remember loving a while ago which is the Empire Trilogy of books by Feist and Wurts &lt;a href="https://en.wikipedia.org/wiki/Empire_Trilogy"&gt;https://en.wikipedia.org/wiki/Empire_Trilogy&lt;/a&gt; One of the things that stuck out to me as I was reading was that the names seemed to be a blend of Korean/Japanese/Chinese/Aztec and seems to follow a standard structure.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Sun, 28 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/generating-harry-potter-spells-and-kelewan-houses/</guid></item><item><title>GraphQL Interfaces vs Unions</title><link>https://danpalmer.me/2018-10-28-graphql-interfaces-vs-unions/</link><description>GraphQL’s type system allows us to make many invalid states impossible to represent, which improves the usability and reliability of our APIs. Two features of the type system that contribute significantly to this are Interfaces and Unions, however they can be used to address similar design considerations so it’s not always obvious which is the right option.
In this post we’ll look at several examples from the Thread API, and explore whether using an interface or a union is the right option.</description><author>Dan Palmer</author><pubDate>Sun, 28 Oct 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://danpalmer.me/2018-10-28-graphql-interfaces-vs-unions/</guid></item><item><title>On NYC, Tokyo and Seoul</title><link>http://notes.eatonphil.com/on-nyc-tokyo-and-seoul.html</link><description>&lt;p&gt;I’ve lived in NYC for the past year — moved here after years in Philly
and after growing up in a rural community a few hours west of
there. My wife is South Korean and last week concluded my second trip
to the suburbs of Seoul to visit her family. We finished up that trip
with a week in Tokyo.&lt;/p&gt;
&lt;p&gt;Long a mecha and Godzilla fan, I was struck by a city not
significantly more modern, or significantly more “Eastern”, than
NYC. In contrast, the lesser known Seoul is more modern than both
cities and shares as much “Eastern” vibe as Tokyo.&lt;/p&gt;
&lt;p&gt;I’d go so far as to say that Seoul is the most livable of the three
for anyone of a similar background. There are a few concrete areas
that led me to this including transportation, apartments, WiFi/cafes,
food, and language.&lt;/p&gt;
&lt;p&gt;I'll conclude with a few tourist recommendations and a list of books
to read on South Korea and Japan if you share my enthusiasm for
comparing life in different cities.&lt;/p&gt;
&lt;h3 id="transportation"&gt;Transportation&lt;/h3&gt;&lt;p&gt;NYC is one of the few cities in the world with a subway that runs
24/7. Tokyo and Seoul do not share this trait despite being many
decades newer. (Tokyo and Seoul were heavily damaged during World War
II and the Korean War, respectively.) And despite being built later,
Tokyo subway cars are even less wide than NYC subway cars (~8.2ft
vs. ~8.5ft).&lt;/p&gt;
&lt;p&gt;In contrast, Seoul subway cars are ~10.2ft wide. The difference may
seem slight but it is noticeable during rush hour when in Seoul there
is space for four people to stand in the aisle versus room for perhaps
two in a Tokyo or NYC subway car.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Seoul subway car" src="https://photos.travelblog.org/Photos/10223/428861/f/4174039-Seoul-subway-car-0.jpg" /&gt;
&lt;small&gt;Seoul subway car, source: Travel Blog&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The Seoul subway system is also the most advanced in terms of
safety. All stations have a floor-to-ceiling barrier with doors that
only open when a train arrives. Most stations in Tokyo have a ~3ft
tall barrier that does the same, though some stations have no
barrier. In NYC there are no barriers anywhere.&lt;/p&gt;
&lt;p&gt;Concerning innovation, Seoul and Tokyo both have multiple driverless
subway lines whereas NYC has none. But in terms of complexity the NYC
subway is the simplest because you pay only once. Seoul and Tokyo
subways are slightly more complex in that you swipe your card when you
enter and exit (or transfer).&lt;/p&gt;
&lt;h4 id="taxis"&gt;Taxis&lt;/h4&gt;&lt;p&gt;It was jarring to be greeted by the very 90s, vaguely British Toyota
Crown taxi cabs that dominate the streets of Tokyo.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Toyota Crown cab" src="https://i.imgur.com/WuIHqxY_d.jpg?maxwidth=640&amp;amp;shape=thumb&amp;amp;fidelity=medium" /&gt;
&lt;small&gt;Source: Phil Eaton&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;These cabs have no integrated navigation unit but a modern unit was
typically mechanically attached. We saw a few of the recently approved
Toyota JPN Taxi, but they only account for around &lt;a href="https://www.japantimes.co.jp/news/2018/05/23/business/taxi-tokyo-prepares-olympic-tourism-boom-accessible-cabs-international-drivers/"&gt;10
percent&lt;/a&gt;
of cabs. (The integrated navigation is massive, perhaps 10-inch
screens.) In contrast, Seoul has a
&lt;a href="http://travel.cnn.com/seoul/life/seoul-taxi-guide-783378/"&gt;variety&lt;/a&gt;
of modern cabs all with integrated navigation — the most common of
which is the Hyundai Sonata.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Hyundai Sonata cab" src="http://www.theseoulguide.com/wp-content/uploads/2013/09/regular_orange_taxi_in_seoul.jpg" /&gt;
&lt;small&gt;Source: The Seoul Guide&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;Although Japanese car companies
&lt;a href="https://www.motortrend.com/news/12q2-1993-eunos-mazda-cosmo-drive/"&gt;pioneered&lt;/a&gt;
integrated navigation in the 90s, it appears to have been the standard
for South Korean car companies for the past 10-20 years.&lt;/p&gt;
&lt;p&gt;And then there’s NYC with its primary mix of Crown Victorias and
Priuses with multiple 4-inch smartphones mechanically attached for
navigation.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://thenypost.files.wordpress.com/2013/10/cab2.jpg?quality=90&amp;amp;strip=all" /&gt;
&lt;small&gt;Source: New York Post&lt;/small&gt;&lt;/p&gt;
&lt;h3 id="living"&gt;Living&lt;/h3&gt;&lt;p&gt;South Korea has no concept of the suburb oriented around single-family
houses. Drive an hour or two out from Seoul or Busan and see the same
massive, modern apartment complexes that are found in the city
center. After that it's the stark farms of Kansas. Japan appears more
like the US in that the city graduates steadily to suburb and farm.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Apartments in Seoul" src="https://cdn.japantimes.2xx.jp/wp-content/uploads/2013/09/wn20130918n2a-870x580.jpg" /&gt;
&lt;small&gt;Apartments in Seoul, source: Japan Times&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;In general, buildings in South Korea are fairly homogeneous. Even the
downtown areas of Seoul have little architectural creativity. Tokyo
and NYC are both diverse in building styles and sizes. However, NYC
takes the cake for ubiquity of massive towers. In fact, the first time
my South Korean father-in-law visited Manhattan he was blown away by
this mass.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Manhattan skyline" src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Manhattan_Skyline_night.jpg/800px-Manhattan_Skyline_night.jpg" /&gt;
&lt;small&gt;New York City, source: Wikipedia&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;The most popular neighborhoods in Tokyo seem more developed than their
Seoul counterparts, the mass of stores and crowds extends further. And
while the average age of buildings in Tokyo seems younger than the
average age of buildings throughout Seoul (including less desirable
areas), the developed areas (including buildings and streets) of Seoul
are significantly cleaner and more modern. In contrast, and on average,
Tokyo buildings seem as old as NYC buildings.&lt;/p&gt;
&lt;p&gt;&lt;img src="https://cdn.fodors.com/wp-content/uploads/2018/02/Tokyo-Neighborhoods-Along-Arakawa-Streetcar-1.jpg" /&gt;
&lt;small&gt;Tokyo, source: Fodors&lt;/small&gt;&lt;/p&gt;
&lt;h4 id="air-quality"&gt;Air quality&lt;/h4&gt;&lt;p&gt;Air quality in &lt;a href="https://www.numbeo.com/pollution/in/New-York"&gt;NYC&lt;/a&gt; and
&lt;a href="https://www.numbeo.com/pollution/in/Tokyo"&gt;Tokyo&lt;/a&gt; is high, pollution
is low. But in &lt;a href="https://www.upi.com/Fine-dust-levels-soar-in-South-Korea/5581523776231/"&gt;recent
times&lt;/a&gt;,
air quality in Seoul has deteriorated with dangerous levels of fine
dust from factories in South Korea and China. It is not clear when or
how the South Korean government will address this.&lt;/p&gt;
&lt;h3 id="wifi/cafes"&gt;WiFi/Cafes&lt;/h3&gt;&lt;p&gt;My idea of a good cafe is a decent ratio of seats to traffic,
available electrical outlets, and decent WiFi. NYC and Tokyo have some
similarities: chain coffee shops are larger and non-chains are often
pretty small. Tokyo differs from NYC in that there are few electrical
outlets and in the existence of interior smoking sections. (Tokyo bans
smoking while walking but designates areas like parks or inner
rooms in restaurants or cafes.)&lt;/p&gt;
&lt;p&gt;But the WiFi in Tokyo is abysmal. Many cafes do not have it (though
the trend is to provide) and even the chains that do provide it have
terrible speeds reaching peaks of 5Mbps down. In NYC WiFi is available
near ~20Mbps down at most chains and ~5Mpbs at smaller non-chains.&lt;/p&gt;
&lt;p&gt;In contrast, South Korea is the jewel of cafe culture. Unlike how in
the US coffee shop size decreases as population increases, coffee shop
sizes in South Korea are oddly enormous everywhere. South Korea is
rich with local shops, domestic chains (including the exported Paris
Baguette and Tous Les Jours), and foreign chains (South Korea has the
highest number of Starbucks Reserve stores per capita of any country).&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://file.mk.co.kr/meet/neds/2018/06/image_readtop_2018_402044_15299876083365412.jpg" /&gt;
&lt;small&gt;Starbucks Reserve in Seoul, source: Pulse News&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;From Jeju Island to Seoul we never worried about a seat or an outlet
at a cafe. Furthermore, the WiFi in South Korea is incredible. My
tech-hopeless in-law’s basic internet plan got 80Mbps down and the
small cafes near their apartment got at least 40Mbps down.&lt;/p&gt;
&lt;p&gt;NYC falls closer to Seoul in terms of ubiquity and speed of WiFi and
has the added benefit of fast city-provided, outdoor WiFi surprisingly
fast and available throughout the city. NYC is much worse in terms of
daylight. Most cafes close between 8-10pm whereas cafes in Seoul and
Tokyo easily stay open past 11pm.&lt;/p&gt;
&lt;h4 id="caveat"&gt;Caveat&lt;/h4&gt;&lt;p&gt;It’s not exactly fair to exclude internet cafes, prevalent in both
Seoul and Tokyo (oddly even NYC has a
&lt;a href="https://www.google.com/maps?q=nyc+internet+cafe&amp;amp;um=1&amp;amp;ie=UTF-8&amp;amp;sa=X&amp;amp;ved=0ahUKEwjE0-PxuZTeAhWTdXAKHYDFB1cQ_AUIDigB"&gt;few&lt;/a&gt;). At
an internet cafe in Tokyo you can expect abundant outlets and
excellent WiFi (I saw peaks of 40Mbps down). I did not visit an
internet cafe in Seoul but I expect it to be similar. In both Seoul
and Tokyo you can easily find 24/7 service (with showers!?).&lt;/p&gt;
&lt;p&gt;I did not include internet cafes above because I find them slightly
less convenient for tourists. Though credit is due: unlike American
Chinatown internet cafes, the ones we visited in Tokyo were very
clean, spacious and warm.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Internet cafe in Shinjuku" src="http://rakutama.com/en/images/shop/koriyama.jpg" /&gt;
&lt;small&gt;Internet cafe in Shinjuku, source: Rakutama&lt;/small&gt;&lt;/p&gt;
&lt;h3 id="food"&gt;Food&lt;/h3&gt;&lt;p&gt;Dining out in NYC is similar in cost to other major US cities. The
quality is usually pretty good. Tokyo was about as expensive as food
in NYC and generally as high quality. For instance, most dinners in
NYC and Tokyo cost about $40-60 for two people. In contrast, most
entrees in Seoul are sold for two and the dinner in total was often
about $20-40. Restaurants on average seemed to be lower quality in
Seoul compared to Tokyo and New York, but there are still more than
enough high quality options.&lt;/p&gt;
&lt;h3 id="language"&gt;Language&lt;/h3&gt;&lt;p&gt;I am biased having a better knowledge of Korean than Japanese and a
South Korean partner to fall back on. But I believe South Korea is the
more friendly place for an English speaker in that it is more
dedicated to providing English translations and that the written
language is simpler. In both cities the penetration of
English-speaking natives (and quality of speech and comprehension) is
indistinguishable and decent.&lt;/p&gt;
&lt;p&gt;To the first point, even the oddest locations and obscure signage had
English translations in South Korea (not just Seoul) — not so even
within Tokyo.&lt;/p&gt;
&lt;p&gt;To the second point, Japanese has three writing systems (kanji,
hiragana, and katakana). Kanji (characters originating from Chinese)
cannot be replaced in writing by phonetic counterparts in hiragana or
katakana. So you have little choice but to memorize all important
characters, disregarding the fact that many characters can be broken
down. Then you must also memorize the alphabetic systems of hiragana
and katakana.&lt;/p&gt;
&lt;p&gt;In contrast, Korean has two writing systems (hangul and hanja) where
hanja (characters originating from Chinese) is primarily used in
formal settings (government forms, academic books, etc.) and can be
replaced with the phonetic equivalent in hangul.&lt;/p&gt;
&lt;p&gt;This makes it much simpler to memorize and read Korean compared to
Japanese.&lt;/p&gt;
&lt;h3 id="assorted-recommendations"&gt;Assorted recommendations&lt;/h3&gt;&lt;p&gt;For New Yorkers, don’t stay in the recommended areas of
Shinjuku/Shibuya/Roppongi unless you’re the type who’d enjoy staying
around Times Square. These three areas of Tokyo are just as obnoxious
albeit much safer. I also don’t recommend the Harajuku area; it is
extra. There’s no real equivalent level of crazy in Seoul although
Hongdae comes close.&lt;/p&gt;
&lt;p&gt;In a future Tokyo trip I’d stick to the Meguro Station area including
Ebisu and Daikanyama. They are beautiful, quiet neighborhoods with
lots of restaurants and cafes beside the Meguro river. Areas along the
Sumida River are also beautiful and quiet. Ginza/Tokyo Station is
also a fun-but-not-obnoxious area to visit.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Ebisu" src="https://odis.homeaway.com/odis/listing/f3fd8dfd-c29e-4ab3-a0cd-19a99bdc3c7f.c10.jpg" /&gt;
&lt;small&gt;Ebisu, source: Homeaway&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;I cannot recommend the Edo-Tokyo Museum enough, it is the best city
museum I've visited. Tsukiji is also a must see, reminding me how much
I miss going to Reading Terminal Market each weekend in Philly.&lt;/p&gt;
&lt;p&gt;In Seoul I’d recommend Yeonnam-Dong, Itaewon (which is much nicer than
it’s made out to be), and Gwanghwamun. Mapo-Gu in general is a great
region of Gangbuk as is the area below it (near Yeouido) in
Gangnam.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Yeonnam-dong" src="https://i.imgur.com/ttdg5Y7.jpg?maxwidth=640" /&gt;
&lt;small&gt;Yeonnam-Dong, source: Phil Eaton&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;I recommend visiting the National Museum of Korea in Seoul as well as
Hangang Park and Gyeongui Line Forest Park. The areas around the
Tancheon stream flowing South to Bundang are also beautiful.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Tancheon near Bundang" src="https://misadventuresofanawkwardamerican.files.wordpress.com/2014/05/dscn05912.jpg" /&gt;
&lt;small&gt;Tancheon near Bundang, source: Misadventures of an Awkward American&lt;/small&gt;&lt;/p&gt;
&lt;h3 id="conclusion"&gt;Conclusion&lt;/h3&gt;&lt;p&gt;I came to Tokyo with the expectation of a highly modern city fused
with Eastern culture. But it is difficult to see many ways it is ahead
of NYC technically and it is very similar to NYC culturally. In some
ways Tokyo even seems a little stuck in the past or just... off. Why
are all vending machines [e.g. for tickets, ordering food, etc.]
mechanical and not touch screens? The National Museum of Science is
awfully old and ugly, the National Diet Building the same.&lt;/p&gt;
&lt;p&gt;So on the one hand I’d like to let the next person down lightly on the
excitement of Japan. It is a world-class city with great restaurants,
live music and refined culture but all-in-all very similar to NYC. On
the other hand I recommend Seoul for a cheaper, cleaner, more
English-speaker friendly, and genuinely novel city with splashes of
"Eastern" romantic elements like Tokyo.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Cherry blossoms in Seoul" src="http://www.englishspectrum.com/wp-content/uploads/2015/03/yeoido.JPG-1.jpg" /&gt;
&lt;small&gt;Cherry blossoms in Seoul, source: English Spectrum&lt;/small&gt;&lt;/p&gt;
&lt;h3 id="further-reading"&gt;Further reading&lt;/h3&gt;&lt;p&gt;&lt;a href="https://amzn.to/2PNOsih"&gt;MITI and the Japanese Miracle: The Growth of Industrial Policy,
1925-1975&lt;/a&gt; is an excellent, albeit somewhat
disputed introduction to the modern Japanese economy.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://amzn.to/2EIw6hc"&gt;Asia’s Next Giant: South Korea and Late
Industrialization&lt;/a&gt; is a similar high-quality
introduction to the South Korean economy.&lt;/p&gt;
&lt;p&gt;If you’re only familiar with
US/Canadian companies or other “pure” market economies these two books
are a great read on different, challenging styles of government
policy, corporate structure, and life.&lt;/p&gt;
&lt;p class="note"&gt;
  P.s. I’m looking for book recommendations on the last 20 years of
  economic/political history in Japan and South Korean and on the last
  100 years of economic/political history in the US and NYC.
&lt;/p&gt;&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Wrote a few points of comparison between &lt;a href="https://twitter.com/hashtag/nyc?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#nyc&lt;/a&gt;, &lt;a href="https://twitter.com/hashtag/seoul?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#seoul&lt;/a&gt;, and &lt;a href="https://twitter.com/hashtag/tokyo?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#tokyo&lt;/a&gt; after finishing a recent trip. &lt;a href="https://t.co/oKo4YlTZV3"&gt;https://t.co/oKo4YlTZV3&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/1053645222402416641?ref_src=twsrc%5Etfw"&gt;October 20, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sat, 20 Oct 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/on-nyc-tokyo-and-seoul.html</guid></item><item><title>3 Tips from Kent C Dodds for People Just Getting Started</title><link>https://www.swyx.io/3-tips-from-kent-c-dodds-for-people-just-getting-started-ik8</link><description>&lt;p&gt;advice for beginners from a podcast&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Tue, 16 Oct 2018 02:54:50 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/3-tips-from-kent-c-dodds-for-people-just-getting-started-ik8</guid></item><item><title>SIGSEGV1 qualification CTF</title><link>https://anisse.astier.eu/qual-sigsegv1-rtfm.html</link><description>&lt;p&gt;After my &lt;a href="r2con-2018.html"&gt;r2con r2wars writeup&lt;/a&gt;, here's another writeup of a "challenge". This challenge is the Capture-The-Flag (CTF) pre-qualifications for the &lt;a href="https://sigsegv1.rtfm.re/"&gt;SIGSEGV1 conference in Paris&lt;/a&gt;. It felt a bit weird to have a conference registration limited to those who pass a certain challenge, but I was curious about what it would …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Fri, 12 Oct 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/qual-sigsegv1-rtfm.html</guid></item><item><title>Networking Essentials: Congestion Control</title><link>https://www.swyx.io/networking-essentials-congestion-control-26n2</link><description>&lt;p&gt;Bottlenecks inevitably arise in networks. How do we deal with them in TCP? How about in practical streaming applications like Youtube and Skype?&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 07 Oct 2018 05:52:44 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-congestion-control-26n2</guid></item><item><title>Using bulk update in Django 2.2</title><link>https://tomforb.es/blog/bulk-update-added-to-django/</link><description>My work on adding bulk_update() to Django has been merged and will be released in Django 2.2! Like my filtered aggregates feature it relies heavily on the wonderfully versatile CASE statement to achieve some pretty good speedups for certain use-cases. The development documentation gives a pretty cle...</description><author>Tom Forbes</author><pubDate>Thu, 04 Oct 2018 21:36:02 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/bulk-update-added-to-django/</guid></item><item><title>how to load initial data and test data in Django 2+</title><link>http://blog.pythonaro.com/2018/08/how-to-load-initial-data-and-test-data.html</link><description>&lt;p&gt;There are two ways to automatically load data in Django: 

&lt;ul&gt;
&lt;li&gt;for data you need while running tests, place xml/json/yaml files in &lt;code&gt;yourapp/fixtures&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;for data you need while setting up the database from scratch, or at specific points in time, you must create a Migration&lt;/li&gt;
&lt;/ul&gt;
&lt;/p&gt;
&lt;p&gt;This is a bit annoying, because chances are these locations will get out of sync sooner or later, and it duplicates effort if you do reproducible builds, docker, and stuff like that.&lt;/p&gt;

&lt;p&gt;The solution is to create a migration that actually loads fixtures. So:
&lt;ol&gt;&lt;li&gt;Create your fixtures: &lt;code&gt;manage.py dumpdata --output yourapp/fixtures/yourmodel.json yourapp.YourModel&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create an empty Migration: &lt;code&gt;manage.py makemigrations --empty yourapp&lt;/code&gt;&lt;li&gt;
&lt;li&gt;Edit the resulting migration (the last file created under &lt;code&gt;yourapp/migrations&lt;/code&gt;, making it look like this:

&lt;pre&gt;
from django.db import migrations

def load_fixtures(apps, schema_editor):
    # This is what will be executed by the migration
    from django.core.management import call_command
    # this is the equivalent of running manage.py loaddata yourmodel.json
    for fixture_name in ['yourmodel']: # add any additional model here
        call_command("loaddata", fixture_name)
    # add other calls if you have multiple models

def rollback(apps, schema_editor):
    # This will be executed if you rollback the migration, so you want to clean up
    for model_name in ["YourModel"]:  # add any additional model here
        model = apps.get_model("yourapp", model_name)
        model.objects.all().delete()

class Migration(migrations.Migration):
    dependencies = [
      # ... don't touch anything here ...
    ]

    operations = [
        migrations.RunPython(load_fixtures, rollback),
    ]
# -*- coding: utf-8 -*-
&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Profit&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Note that this does not remove the option to have data that is available only in certain situation: just don't list the fixtures you don't want in the migration, and vice-versa.&lt;/p&gt;</description><author>Subclassed</author><pubDate>Thu, 04 Oct 2018 15:42:41 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/08/how-to-load-initial-data-and-test-data.html</guid></item><item><title>Fix Missing Headers Compiling on macOS Mojave</title><link>https://donatstudios.com/MojaveMissingHeaderFiles</link><description>&lt;fieldset&gt;
&lt;legend&gt;Update&lt;/legend&gt;

It would appear that the latest version of Xcode has removed the macOS_SDK_headers_for_macOS_10.14.pkg file. I am currently searching for alternative solutions.

&lt;/fieldset&gt;
&lt;p&gt;While trying to compile PHP extensions after installing macOS Mojave, I was butting up against a ton of missing header file errors including &lt;code&gt;php.h&lt;/code&gt; and zlib.&lt;/p&gt;
&lt;p&gt;After several hours of beating my head against my desk and Googling/Stack Overflowing I found the solution.&lt;/p&gt;
&lt;p&gt;Ends up you just need to force re-install the header files. Special thanks to &lt;a href="https://github.com/Homebrew/homebrew-core/issues/29176#issuecomment-398656987"&gt;@sfdye&lt;/a&gt; for the solution!&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you get an error about that file not existing, you probably simply don't have the Xcode command line tools installed which can be remedied simply as follows:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ xcode-select --install&lt;/code&gt;&lt;/pre&gt;</description><author>Donat Studios</author><pubDate>Wed, 03 Oct 2018 00:22:40 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/MojaveMissingHeaderFiles</guid></item><item><title>Blogtober 2018, the second</title><link>https://rjp.is/blogging/posts/blogtober-2018-02/</link><description>In which we fail dismally at all the 'obers.</description><author>infrequent oscillations</author><pubDate>Tue, 02 Oct 2018 21:44:19 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/blogtober-2018-02/</guid></item><item><title>Blogtober 2018, the first</title><link>https://rjp.is/blogging/posts/blogtober-2018-01/</link><description>In which we try to follow some 'obers.</description><author>infrequent oscillations</author><pubDate>Mon, 01 Oct 2018 22:31:06 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/blogtober-2018-01/</guid></item><item><title>Trifecta of Obers</title><link>https://rjp.is/blogging/posts/trifecta-of-obers/</link><description>In which we make plans we fail to keep.</description><author>infrequent oscillations</author><pubDate>Sun, 30 Sep 2018 20:01:54 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/trifecta-of-obers/</guid></item><item><title>Solving My Email Problem - Followup</title><link>https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem-followup/</link><description>&lt;p&gt;My last
&lt;a class="reference external" href="https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem/"&gt;post&lt;/a&gt;
got quite a few
&lt;a class="reference external" href="https://news.ycombinator.com/item?id=18100807"&gt;comments&lt;/a&gt; on Hacker
News. They did force me to think a little, and here I&amp;#8217;ll gather some of
my&amp;nbsp;thoughts.&lt;/p&gt;
&lt;div class="section" id="i-have-an-email-workflow-that-is-different-from-yours"&gt;
&lt;h2&gt;&lt;span class="dquo"&gt;&amp;#8220;&lt;/span&gt;I have an email workflow that is different from&amp;nbsp;yours&amp;#8221;&lt;/h2&gt;
&lt;p&gt;If you&amp;#8217;re happy with your email setup, I am by no …&lt;/p&gt;&lt;/div&gt;</description><author>Beetle Space</author><pubDate>Sat, 29 Sep 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem-followup/</guid></item><item><title>Solving My Email Problem</title><link>https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem/</link><description>&lt;p&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Email is not a messaging protocol. It&amp;#8217;s a &lt;span class="caps"&gt;TODO&lt;/span&gt; list. Or at least my
inbox is a &lt;span class="caps"&gt;TODO&lt;/span&gt; list and email is the protocol for putting stuff on
it. Here&amp;#8217;s the problem. It is a s**tty &lt;span class="caps"&gt;TODO&lt;/span&gt; list. Any one of you can
put something on my …&lt;/p&gt;&lt;/blockquote&gt;</description><author>Beetle Space</author><pubDate>Fri, 28 Sep 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2018/Sep/solving-my-email-problem/</guid></item><item><title>Networking Essentials: DNS</title><link>https://www.swyx.io/networking-essentials-dns-1dl7</link><description>&lt;p&gt;Domain names, you buy them, you sell them, but how do they work?&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 26 Sep 2018 07:12:12 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-dns-1dl7</guid></item><item><title>Networking Essentials: Router Design</title><link>https://www.swyx.io/networking-essentials-router-design-ahc</link><description>&lt;p&gt;A small detour into Router Hardware!&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 26 Sep 2018 06:33:05 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-router-design-ahc</guid></item><item><title>Why (and how) to read books</title><link>http://notes.eatonphil.com/why-and-how-to-read-books.html</link><description>&lt;p&gt;The last time I read for fun was in elementary school. Since college I
knew I must read more, but I never forced myself to build the
habit. Then three years ago I spent time around my brother and a
coworker who were avid readers. This "peer pressure" helped me get
started.&lt;/p&gt;
&lt;p&gt;Since I started, I've seen concrete improvements in vocabulary. I find
myself using words I didn't know I knew. I question my choice of words
more. And I understand coworkers a little better. Perhaps it is only
personal style, but I've also become more aware of hyperbole in my
speech and have begun to tone that down.&lt;/p&gt;
&lt;p&gt;Specifically, books provide more density of information than I can
pull together myself. I've also benefited heavily from reading books
on tools I use daily. Contrary to being boring, a book on a topic with
which I'm familiar has been a (often needed) break from books on
topics with which I am unfamiliar. The former category might include
books on CSS, Bash, Emacs, Python, Scheme, data modeling,
Linux/FreeBSD system administration, mystery novels, and so on. The
latter category might include books on Common Lisp, system
architecture, the implementation of Linux/FreeBSD, behavioral
psychology, management, stock/bond markets, the history of
Argentina/Chile/South Korea/Japan, sci-fi novels, and so on.&lt;/p&gt;
&lt;p&gt;Reading diversely exposes how little I know. And that can be
depressing. But I'm fairly confident reading books is the fastest way
to grow.&lt;/p&gt;
&lt;p&gt;Tactically speaking, I started slowly with few books and the ones
easiest for me to read. The first year I read two books, both
technical. The second year I read nine books and was able to start
branching out beyond technical books. Last year I read a much more
diverse set of forty books. And this year I followed suit with
forty-one so far (on track for fifty-five or so).&lt;/p&gt;
&lt;p&gt;I keep track of books I'm reading and books I want to read in
&lt;a href="https://www.goodreads.com/eatonphil"&gt;Goodreads&lt;/a&gt;. I particularly enjoy
their reading challenge system that lets you know if you are on track
to meet your reading goal for the year.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Wed, 26 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/why-and-how-to-read-books.html</guid></item><item><title>Kernel Recipes 2018 liveblog</title><link>https://anisse.astier.eu/recipes-conferences-2018.html</link><description>&lt;p&gt;I had a lot of good feedback from the &lt;a href="kernel-recipes-2017-day-1"&gt;previous&lt;/a&gt; &lt;a href="kernel-recipes-2016-notes.html"&gt;years&lt;/a&gt; live-blogs of the Embedded and Kernel Recipes conferences. So much in fact, that this year I'm now doing the liveblog &lt;a href="https://kernel-recipes.org/en/2018/live-blog/"&gt;directly on the official website of kernel recipes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope you enjoy it !&lt;/p&gt;
&lt;p&gt;I also live-tweeted my impressions of …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Wed, 26 Sep 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/recipes-conferences-2018.html</guid></item><item><title>Warehouse locations with k-means</title><link>https://bytepawn.com/warehouse-locations-with-kmeans.html</link><description>&lt;p&gt;Sometimes, the seven gods of data science, Pascal, Gauss, Bayes, Poisson, Markov, Shannon  and Fisher, all wake up in a good mood, and things just work out. Recently we had such an occurence at Fetchr, when the Operational Excellence team posed the following question: &lt;i&gt;if we could pick our Saudi warehouse locations, where would be put them? What is the ideal number of warehouses, and, what does ideal even mean? Also, what should our “delivery radius” be?&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;img alt="." src="/images/pickup_locations_riyadh.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Wed, 26 Sep 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/warehouse-locations-with-kmeans.html</guid></item><item><title>Networking Essentials: Naming, Addressing, and Forwarding</title><link>https://www.swyx.io/networking-essentials-naming-addressing-and-forwarding-13kk</link><description>&lt;p&gt;How IP Addressing evolved over time, how it works today, and how we can transition to IPv6 in future&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sun, 23 Sep 2018 18:39:34 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-naming-addressing-and-forwarding-13kk</guid></item><item><title>Postgres 11 - A First Look</title><link>/2018/09/20/postgresql-11-a-first-look/</link><description>&lt;p&gt;Postgres 11 is almost here, in fact the latest beta shipped today, and it features a lot of exciting improvements. If you want to get the full list of features it is definitely worth checking out the &lt;a href="https://www.postgresql.org/docs/11/static/release-11.html"&gt;release notes&lt;/a&gt;, but for those who don&amp;rsquo;t read the release notes I put together a run down of some what I consider the highlight features.&lt;/p&gt;
&lt;h2 id="quitting-postgres"&gt;
&lt;div&gt;
Quitting Postgres
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;This is a small usability feature, but so long over due. Now you can quit Postgres by simply typing &lt;code&gt;quit&lt;/code&gt; or &lt;code&gt;exit&lt;/code&gt;. Previously you had to use Ctrl + D or &lt;code&gt;\q&lt;/code&gt;. As a begginer it&amp;rsquo;s one thing to jump into a psql terminal, but once in if you can&amp;rsquo;t figure out how to quit it&amp;rsquo;s a frustrating experience. Small usability features, such as this and &lt;code&gt;watch&lt;/code&gt; in an earlier release, are often lost in the highlighted features which talk about performance or new data types. Improvements like this really go a long way for making Postgres a better database for everyone.&lt;/p&gt;
&lt;h2 id="fear-column-addition-no-more"&gt;
&lt;div&gt;
Fear column addition no more
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://brandur.org/postgres-default"&gt;Brandur&lt;/a&gt; had a great in depth write-up on this feature already, but it falls somewhere into the category of the above as well as a performance improvement. Previously when you added a new column that was &lt;code&gt;NOT NULL&lt;/code&gt; with a default value Postgres would have to take a lock and re-write the entire table. In a production environment on any sizable table for all practical purposes the result was an outage. The work around was to break your migrations apart to be a several &lt;a href="https://blog.codeship.com/rails-migrations-zero-downtime/"&gt;step process&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With Postgres 11 you can add a new column to a table that is not null with a default value. The new row will get materialized on your database without requiring a full re-write. Here is to having to think less about your migrations.&lt;/p&gt;
&lt;h2 id="of-course-performance-is-a-highlight"&gt;
&lt;div&gt;
Of course performance is a highlight
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;No Postgres release would be complete without some performance improvements. This release there are really two areas that feature key improvements around performance.&lt;/p&gt;
&lt;h3 id="parallelism-continuing-to-mature"&gt;
&lt;div&gt;
Parallelism continuing to mature
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;We first saw parallelism support back in PostgreSQL 9.6. At the time it was primarily for sequential scans, which if you used parallelism for your sequential scans was great, but overall that was a narrow focus. PostgreSQL 10 parallelism because much more useful, and with PostgreSQL 11 it just keeps getting better. Some of the highlights for parallelism include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parallel hash joins&lt;/li&gt;
&lt;li&gt;Parallel append&lt;/li&gt;
&lt;li&gt;Parallel index creation - &lt;em&gt;We&amp;rsquo;ve talked about how great this can be over on the &lt;a href="https://www.citusdata.com/blog/2017/01/17/parallel-indexing-with-citus/"&gt;Citus blog&lt;/a&gt;. With it natively in Postgres it makes it even easier for people to leverage.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to dig deeper into all the parallelism support in Postgres &lt;a href="https://speakerdeck.com/macdice/parallelism-in-postgresql-11"&gt;this presentation&lt;/a&gt; by PostgreSQL committer Thomas Munro at &lt;a href="https://2018.postgresopen.org/"&gt;PostgresOpen Silicon Valley&lt;/a&gt; from a few weeks ago is a great resource.&lt;/p&gt;
&lt;h3 id="postgres-gets-a-jit"&gt;
&lt;div&gt;
Postgres gets a JIT
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Just in time compilation is going to be a big deal for Postgres for the coming years. We have the initial support for it now in PostgreSQL 11. Even in this initial implementation of JIT support you can see a nearly 30% speedup on certain queries, such as highlighted here by the &lt;a href="https://www.citusdata.com/blog/2018/09/11/postgresql-11-just-in-time/"&gt;TPC-H benchmark&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It is still early days for the just in time query compilation support, so expect the improvements here to be even better in PostgreSQL 12 and 13.&lt;/p&gt;
&lt;h2 id="statistics-keep-getting-better"&gt;
&lt;div&gt;
Statistics keep getting better
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;In Postgres 10 we saw a feature that few have probably used &lt;a href="https://www.citusdata.com/blog/2018/03/06/postgres-planner-and-its-usage-of-statistics/"&gt;&lt;code&gt;CREATE STATISTICS&lt;/code&gt;&lt;/a&gt;. You see under the covers Postgres keeps a lot of information about your database which it uses to determine the query plan it will use when executing a query. Most statistics were single column ones previously, now with &lt;code&gt;CREATE STATISTICS&lt;/code&gt; you could define a correlation between two separate columns. With Postgres 11 now you can create statistics based on expression indexes giving you even more cases where they can help the performance of your app.&lt;/p&gt;
&lt;h2 id="keeping-standbys-warm"&gt;
&lt;div&gt;
Keeping standbys warm
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;pg_prewarm&lt;/code&gt; has been great for warming up a replica&amp;rsquo;s cache so that should you have a failover you&amp;rsquo;re not failing over to a cold cache. However up until PostgreSQL 11 you&amp;rsquo;d have to manually run it yourself or setup some scheduler such as &lt;a href="https://www.citusdata.com/blog/2016/09/09/pgcron-run-periodic-jobs-in-postgres/"&gt;pg_cron&lt;/a&gt;, now you can configure &lt;code&gt;pg_prewarm&lt;/code&gt; to run all on it&amp;rsquo;s own at a regular interval.&lt;/p&gt;
&lt;h2 id="and-more"&gt;
&lt;div&gt;
And more
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;PostgreSQL 11 is packed with more features than I&amp;rsquo;ve seen in a release before, though I think I&amp;rsquo;ve also said that before. It will be exciting to see several of these features such as the JIT support, statistics, and others as it is still in the early days for them. Meanwhile we have a great set of new features to improve user experience as well as help performance with parallelism. If you&amp;rsquo;re curious to get your hands on these give the &lt;a href="https://www.postgresql.org/about/news/1890/"&gt;beta&lt;/a&gt; a try and send your feedback to the PostgreSQL community.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Thu, 20 Sep 2018 23:55:56 GMT</pubDate><guid isPermaLink="true">/2018/09/20/postgresql-11-a-first-look/</guid></item><item><title>Sloc Cloc and Code Revisited - Optimizing an already fast Go application</title><link>https://boyter.org/posts/sloc-cloc-code-performance/</link><description>&lt;p&gt;&lt;strong&gt;Update 2019-03-13&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is now part of a series of blog posts about &lt;code&gt;scc&lt;/code&gt; Sloc Cloc and Code which has now been optimised to be the fastest code counter for almost every workload. Read more about it at the following links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;Sloc Cloc and Code - What happened on the way to faster Cloc 2018-04-16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-revisited/"&gt;Sloc Cloc and Code Revisited - A focus on accuracy 2018-08-28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance/"&gt;Sloc Cloc and Code Revisited - Optimizing an already fast Go application 2018-09-19&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance-update/"&gt;Sloc Cloc and Code a Performance Update 2019-01-09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-badges/"&gt;Sloc Cloc and Code Badges for Github/Bitbucket/Gitlab&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don&amp;rsquo;t want to make any false claims about the impact of &lt;code&gt;scc&lt;/code&gt; and the blog post about it &lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;https://boyter.org/posts/sloc-cloc-code/&lt;/a&gt; but following its release both &lt;code&gt;tokei&lt;/code&gt; and &lt;code&gt;loc&lt;/code&gt; were updated with impressive performance improvements. In addition a new tool &lt;code&gt;polyglot&lt;/code&gt; &lt;a href="http://blog.vmchale.com/article/polyglot-comparisons"&gt;http://blog.vmchale.com/article/polyglot-comparisons&lt;/a&gt; was released which also claimed performance as its main feature. Lastly the tool &lt;code&gt;gocloc&lt;/code&gt; &lt;a href="https://github.com/hhatto/gocloc"&gt;https://github.com/hhatto/gocloc&lt;/a&gt; appears to be getting updates as well. All good stuff.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Wed, 19 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/sloc-cloc-code-performance/</guid></item><item><title>Growth Accounting and Backtraced Growth Accounting</title><link>https://bytepawn.com/backtraced-growth-accounting.html</link><description>&lt;p&gt;Previously I wrote two articles about data infra and data engineering at Fetchr. This time I want to move up the stack and talk about a simple piece of metrics engineering that proved to be very impactful: Growth Accounting and Backtraced Growth Accounting.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Backtraced Growth Accounting" src="/images/ga_read_off.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Sun, 16 Sep 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/backtraced-growth-accounting.html</guid></item><item><title>Networking Essentials: Routing</title><link>https://www.swyx.io/networking-essentials-routing-5gb7</link><description>&lt;p&gt;How the Internet cobbles together thousands of Autonomous Systems with the Border Gateway Protocol&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 15 Sep 2018 10:25:35 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-routing-5gb7</guid></item><item><title>Aadhaar Vulnerability Public Disclosure</title><link>https://captnemo.in/blog/2018/09/15/aadhaar-disclosure/</link><description>&lt;h1 id="the-vulnerability"&gt;The Vulnerability&lt;/h1&gt;

&lt;p&gt;The UIDAI Resident Portal (with read access to entire Aadhaar Demographic data) is runing a vulnerable version
of LifeRay software. It is running LifeRay 6.1, which was declared End-of-Life in Febrary 2016.&lt;/p&gt;

&lt;p&gt;This release includes multiple known vulnerabilities, including:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;A XSS issue, for which a PoC can be found at &lt;a href="https://resident.uidai.gov.in/?cdn_host=https://scan.bb8.fun"&gt;resident.uidai.gov.in&lt;/a&gt; (Picture Credits: &lt;a href="https://twitter.com/sanitarypanels"&gt;@sanitarypanels&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;Multiple RCEs: See &lt;a href="https://dev.liferay.com/web/community-security-team/known-vulnerabilities/liferay-portal-62"&gt;issue-62&lt;/a&gt; for eg.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In fact the release is so old it does not even appear on the &lt;a href="https://portal.liferay.dev/learn/security/known-vulnerabilities"&gt;“Known Vulnerabilities”&lt;/a&gt; page on the LifeRay website; you have to go look at their &lt;a href="https://dev.liferay.com/web/community-security-team/known-vulnerabilities/liferay-portal-62"&gt;Archived Vulnerabilities&lt;/a&gt;.&lt;/p&gt;

&lt;h1 id="the-poc"&gt;The PoC&lt;/h1&gt;

&lt;p&gt;You can find a simple Proof of Concept for the XSS issue at &lt;a href="https://resident.uidai.gov.in/?cdn_host=https://scan.bb8.fun"&gt;resident.uidai.gov.in&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class="language-plaintext highlighter-rouge"&gt;cdn_host&lt;/code&gt; parameter injects javascript from &lt;code class="language-plaintext highlighter-rouge"&gt;$CDN_HOST/Resident-theme/js/custom.js&lt;/code&gt;, in this case &lt;code class="language-plaintext highlighter-rouge"&gt;https://scan.bb8.fun/Resident-theme/js/custom.js&lt;/code&gt; which hosts a small snippet to overwrite the HTML of the page.&lt;/p&gt;

&lt;p&gt;It shows up like:&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="/img/aadhaar1.jpg" /&gt;&lt;/p&gt;

&lt;h1 id="fun"&gt;Fun&lt;/h1&gt;

&lt;p&gt;The current script allows for embeding any tweet using a &lt;code class="language-plaintext highlighter-rouge"&gt;tweet&lt;/code&gt; parameter. To embed:&lt;/p&gt;

&lt;p&gt;Go to any tweet, copy the part after &lt;code class="language-plaintext highlighter-rouge"&gt;twitter.com&lt;/code&gt; and pass it as the &lt;code class="language-plaintext highlighter-rouge"&gt;tweet&lt;/code&gt; parameter. For eg, to embed this tweet:&lt;/p&gt;

&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Breaking: Exclusive footage from inside &lt;a href="https://twitter.com/UIDAI?ref_src=twsrc%5Etfw"&gt;@UIDAI&lt;/a&gt;'s IT department after media reports of Aadhaar data leaks. &lt;a href="https://t.co/W7m9L0HvEX"&gt;pic.twitter.com/W7m9L0HvEX&lt;/a&gt;&lt;/p&gt;&amp;mdash; Aadhaar Compound Wall (@13footwall) &lt;a href="https://twitter.com/13footwall/status/979301578686345216?ref_src=twsrc%5Etfw"&gt;March 29, 2018&lt;/a&gt;&lt;/blockquote&gt;


&lt;ol&gt;
  &lt;li&gt;Look at the URL: &lt;code class="language-plaintext highlighter-rouge"&gt;https://twitter.com/13footwall/status/979301578686345216&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Copy &lt;code class="language-plaintext highlighter-rouge"&gt;13footwall/status/979301578686345216&lt;/code&gt; and pass it as the &lt;code class="language-plaintext highlighter-rouge"&gt;tweet parameter&lt;/code&gt;:&lt;/li&gt;
  &lt;li&gt;The URL becomes&lt;code class="language-plaintext highlighter-rouge"&gt;https://resident.uidai.gov.in/?cdn_host=https://scan.bb8.fun&amp;amp;tweet=13footwall/status/979301578686345216&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://resident.uidai.gov.in/?cdn_host=https://scan.bb8.fun&amp;amp;tweet=13footwall/status/979301578686345216"&gt;&lt;strong&gt;SHARE IT&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id="the-report"&gt;The Report&lt;/h1&gt;

&lt;p&gt;I initially reported this to &lt;code class="language-plaintext highlighter-rouge"&gt;help@uidai.gov.in&lt;/code&gt; in Jan 2017:&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="/img/aadhaar-report1.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;Forgot all about it till Jan 2018, when someone mentioned I should try my luck with CERT-IN instead:&lt;/p&gt;

&lt;p&gt;&lt;img alt="" src="/img/aadhaar-report2.png" /&gt;&lt;/p&gt;

&lt;h1 id="update"&gt;Update&lt;/h1&gt;

&lt;p&gt;There is &lt;a href="https://twitter.com/kingslyj/status/1040985678408871937"&gt;some confusion&lt;/a&gt; regarding which version of LifeRay
is UIDAI running. They seem to be running 6.1.1, released in 2013-02-26.&lt;/p&gt;

&lt;p&gt;The exact version is not relevant to the fact that UIDAI is:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;running an unsupported release&lt;/li&gt;
  &lt;li&gt;which is 5 year old&lt;/li&gt;
  &lt;li&gt;not updating it despite being notified multiple times&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;0800 16-Sep&lt;/em&gt;: UIDAI seems to have patched the issue by putting a block on the &lt;code class="language-plaintext highlighter-rouge"&gt;cdn_host&lt;/code&gt; parameter. This still leaves them vulnerable to multiple vulnerabilities until they update to a supported release.&lt;/p&gt;

&lt;h1 id="timeline"&gt;Timeline&lt;/h1&gt;

&lt;p&gt;The vulnerability is still not fixed. Here is a complete timeline:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Date&lt;/th&gt;
      &lt;th&gt;What?&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;16 Jan 2017&lt;/td&gt;
      &lt;td&gt;Initially reported to &lt;code class="language-plaintext highlighter-rouge"&gt;help@uidai.gov.in&lt;/code&gt;. No response&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;21 Jan 2018&lt;/td&gt;
      &lt;td&gt;Reported to &lt;code class="language-plaintext highlighter-rouge"&gt;ceo@uidai.gov.in&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;info@cert-in.org.in&lt;/code&gt;. No response&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;19 Feb 2018&lt;/td&gt;
      &lt;td&gt;Reminder sent to &lt;code class="language-plaintext highlighter-rouge"&gt;ceo@uidai.gov.in&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;info@cert-in.org.in&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;19 Feb 2018&lt;/td&gt;
      &lt;td&gt;Acknowledgement from CERT&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;15 Mar 2018&lt;/td&gt;
      &lt;td&gt;Reminder sent. No response&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;17 Mar 2018&lt;/td&gt;
      &lt;td&gt;Notified &lt;a href="mailto:rvdp@nciipc.gov.in"&gt;NCIIPC&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;18 Mar 2018&lt;/td&gt;
      &lt;td&gt;Confirmation from NCIIPC asking for more details. I replied back with a quote of previous exchange&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;19 Mar 2018&lt;/td&gt;
      &lt;td&gt;Confirmation from NCIIPC thanking me for the report.&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;19 Apr 2018&lt;/td&gt;
      &lt;td&gt;Reminder sent to UIDAI asking for acknowledgement&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;30 May 2018&lt;/td&gt;
      &lt;td&gt;Reminder sent to NCIIPC and CERT asking for updates&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The only change that I’m aware of since my initial report is that the website stopped declaring the &lt;a href="https://en.wikipedia.org/wiki/Security_through_obscurity"&gt;LifeRay version in a HTTP response Header&lt;/a&gt;.&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sat, 15 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/09/15/aadhaar-disclosure/</guid></item><item><title>The Rise of Immer in React</title><link>https://www.swyx.io/rise-of-immer</link><description>&lt;blockquote&gt;
&lt;p&gt;2018: &lt;em&gt;Published on the Netlify Blog as &lt;a href="https://www.netlify.com/blog/2018/09/12/the-rise-of-immer-in-react/"&gt;The Rise of Immer in React&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 12 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/rise-of-immer</guid></item><item><title>r2con 2018 and r2wars</title><link>https://anisse.astier.eu/r2con-2018.html</link><description>&lt;p&gt;I tried something new this year, by going to &lt;a href="https://rada.re/con/2018"&gt;r2con&lt;/a&gt;, a conference dedicated to &lt;a href="https://radare.org"&gt;radare2&lt;/a&gt;, a reverse engineering toolkit.&lt;/p&gt;
&lt;h1&gt;r2con&lt;/h1&gt;
&lt;p&gt;This conference is one of the most affordable security conference out there. I've used radare2 (r2) in the past, but I don't think I fully understood its philosophy until going …&lt;/p&gt;</description><author>Linux Engineer's random thoughts</author><pubDate>Sat, 08 Sep 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://anisse.astier.eu/r2con-2018.html</guid></item><item><title>Networking Essentials: Switching</title><link>https://www.swyx.io/networking-essentials-switching-3eba</link><description>&lt;p&gt;Discussing why we need Switches in a network and how they work&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 05 Sep 2018 00:01:50 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-switching-3eba</guid></item><item><title>Networking Essentials: Architecture and Principles</title><link>https://www.swyx.io/networking-essentials-architecture-and-principles-2g5e</link><description>&lt;p&gt;Discussing the architecture of the Internet and its the principles that guided its original design.&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Tue, 04 Sep 2018 12:18:56 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/networking-essentials-architecture-and-principles-2g5e</guid></item><item><title>Compiling dynamic programming languages</title><link>http://notes.eatonphil.com/compiling-dynamic-programming-languages.html</link><description>&lt;p&gt;It can be difficult to disassociate the idea that dynamically typed
programming languages are tied to byte-code interpreters (e.g. YARV
Ruby, CPython, V8, Zend Engine, etc.). But for many languages, a
compiled implementation also exists. Cython, Chicken Scheme and SBCL
are good examples.&lt;/p&gt;
&lt;p&gt;In this post I will briefly describe how I built a compiler for my
&lt;a href="https://github.com/eatonphil/bsdscheme"&gt;Scheme implementation&lt;/a&gt; using
artifacts from the interpreter. In doing this, I learned a simple (not
novel) technique for compiling dynamic languages. I'll introduce the
&lt;a href="https://github.com/eatonphil/jsc"&gt;Javascript to C++/V8 compiler&lt;/a&gt; I
am developing using this technique.&lt;/p&gt;
&lt;h3 id="bsdscheme"&gt;BSDScheme&lt;/h3&gt;&lt;p&gt;For the past year I've developed a Scheme implementation,
&lt;a href="https://github.com/eatonphil/bsdscheme"&gt;BSDScheme&lt;/a&gt;. I started with an
AST-interpreter (as opposed to a byte-code compiler and VM). A more
detailed blog post on the first few steps writing BSDScheme can be
found
&lt;a href="http://notes.eatonphil.com/first-few-hurdles-writing-a-scheme-interpreter.html"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As I built up support for the various objects and operations in the
language, I had a sizeable base of D code for the BSDScheme
runtime. This included an object representation for primitive types
(and support for converting to and from types in D) as well as basic
Scheme operations
(&lt;code&gt;+&lt;/code&gt;, &lt;code&gt;-&lt;/code&gt;, &lt;code&gt;car&lt;/code&gt;, &lt;code&gt;cdr&lt;/code&gt;,
etc.).&lt;/p&gt;
&lt;p&gt;When the time came to implement a compiler backend, I only needed to
do codegen since the parser already existed. Furthermore, the
fundamental bits had already been written: object representation and
much of the standard library. So I wrote the simplest compiler I could
think of by targeting D and the objects/functions I had already
written to support the interpreter.&lt;/p&gt;
&lt;p&gt;Take, for example, the &lt;code&gt;equals&lt;/code&gt;
&lt;a href="https://github.com/eatonphil/bsdscheme/blob/master/src/common.d#L140"&gt;function&lt;/a&gt;
in the standard library:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToList&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;auto&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;switch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tagOfValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;ValueTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueIsInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;ValueTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Char&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueIsChar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToChar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToChar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;ValueTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;String&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueIsString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;ValueTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueIsSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToSymbol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;ValueTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueIsFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;ValueTag&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="no"&gt;Bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueIsBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;valueToBool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;makeBoolValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So long as my compiler generated code that used the &lt;code&gt;Value&lt;/code&gt;
object to represent Scheme data, I already had an &lt;code&gt;equals&lt;/code&gt;
function and large swaths of a Scheme standard library that I could
share between the compiler and interpreter.&lt;/p&gt;
&lt;p&gt;Ultimately I only needed to implement a few control structures to
support compiling a large subset of what I supported in the
interpreter. The key aspects here include: function definitions (in
D), function calls (D function calls), if/else (if/else in D) and so
on.&lt;/p&gt;
&lt;p&gt;To give a concrete example of a whole program compiled, this Scheme program:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)))))&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;define&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;display&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;exp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;newline&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;when run through the BSDScheme compiler would become:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;common&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utility&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;listToVector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;equals_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;equals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorToList&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;makeIntegerValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;if_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;truthy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;equals_result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;makeIntegerValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;if_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;makeIntegerValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;minus_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;minus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorToList&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;makeIntegerValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exp_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorToList&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;minus_result&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorToList&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exp_result&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;if_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;times_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;if_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;BSDScheme_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exp_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorToList&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;makeIntegerValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;makeIntegerValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;display_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;display&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorToList&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;exp_result&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;newline_result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;newline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vectorToList&lt;/span&gt;&lt;span class="p"&gt;([]),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;newline_result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;BSDScheme_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nilValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Where &lt;em&gt;every imported function had already been written for the
interpreter&lt;/em&gt;. I had only to translate a few lines to D and import/call
these existing libraries. Now I had a small &lt;em&gt;binary&lt;/em&gt; of compiled
Scheme.&lt;/p&gt;
&lt;p&gt;It was at this point I realized I was using the same technique used by
Cython to compile Python code.&lt;/p&gt;
&lt;p class="note"&gt;
  ...the Cython project has approached this problem by means of a
  source code compiler that translates Python code to equivalent C
  code. This code is executed within the CPython runtime environment,
  but at the speed of compiled C and with the ability to call directly
  into C libraries.

  &lt;a href="http://docs.cython.org/en/latest/src/quickstart/overview.html"&gt;
    http://docs.cython.org/en/latest/src/quickstart/overview.html
  &lt;/a&gt;
&lt;/p&gt;&lt;h3 id="jsc"&gt;jsc&lt;/h3&gt;&lt;p&gt;I played with many PL-research-y languages over the years and wanted
to do build something a little more practical. So I took what I
learned writing the BSDScheme compiler and decided to write a
Javascript compiler. Specifically, it would target the easiest backend
I could imagine: C++ using the V8 C++ library and generating a Node
addon.&lt;/p&gt;
&lt;p&gt;There already existed well-trodden guides/means of writing Node addons
in C++ so I spent some time trying to hand-compile simple Javascript
programs to C++ and V8. A string in Javascript would become a
&lt;code&gt;v8::String&lt;/code&gt; type in C++. A number in Javascript would become
&lt;code&gt;v8::Number&lt;/code&gt; in C++ and so forth.&lt;/p&gt;
&lt;p&gt;I decided to write this compiler in Rust given its roots in (and my
familiarity with) ML and Python. I found a &lt;a href="https://github.com/dherman/esprit"&gt;Javascript parser by Dave
Herman&lt;/a&gt; and after a few lazy weeks
finally got a "Hello world!" program compiling. Getting my first
program to compile has by far been the hardest part of building jsc.&lt;/p&gt;
&lt;p&gt;Let's look at a concrete example of a recursive fibonacci program
(example/recursion.js in the
&lt;a href="https://github.com/eatonphil/jsc"&gt;repo&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;20&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let's add a call to &lt;code&gt;main()&lt;/code&gt; at the end and time this with
Node to get a baseline:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;example/recursion.js
&lt;span class="m"&gt;6765&lt;/span&gt;
node&lt;span class="w"&gt; &lt;/span&gt;example/recursion.js&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.06s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.02s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;97&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.083&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now let's install jsc to compare. We'll need Rust, Cargo, Node and
Node-GYP.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https:/github.com/eatonphil/jsc
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;jsc
$&lt;span class="w"&gt; &lt;/span&gt;make&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;make&lt;span class="w"&gt; &lt;/span&gt;install
$&lt;span class="w"&gt; &lt;/span&gt;jsc&lt;span class="w"&gt; &lt;/span&gt;example/recursion.js
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;jsc produces a Javascript entrypoint that imports our addon
(build/recursion.js):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;./build/Release/recursion&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;jsc_main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And it produces a C++ file that represents the entire program
(build/recursion.cc):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;string&amp;gt;&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="cpf"&gt;&amp;lt;node.h&amp;gt;&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FunctionCallbackInfo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Isolate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;False&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v8&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FunctionCallbackInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Isolate&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetIsolate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="nl"&gt;tail_recurse_1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx_2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetCurrentContext&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;global_3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ctx_2&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Global&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Boolean_4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;global_3&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NewFromUtf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Boolean&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Utf8Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utf8value_tmp_5&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string_tmp_6&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;utf8value_tmp_5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Utf8Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;utf8value_tmp_7&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string_tmp_8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;utf8value_tmp_7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_9&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string_tmp_6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;string_tmp_8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;False&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Boolean_4&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_10&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToBoolean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetReturnValue&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg_11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ftpl_13&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_12&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ftpl_13&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;fn_12&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;SetName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NewFromUtf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fib&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_14&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg_11&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_12&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_14&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg_16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ftpl_18&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ftpl_18&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;fn_17&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;SetName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NewFromUtf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fib&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_19&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg_16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_17&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_19&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetReturnValue&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;result_15&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_20&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsString&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result_15&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_20&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;result_15&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;||&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_20&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;IsNumber&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_15&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_20&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;ToNumber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;()))&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;))));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;jsc_main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FunctionCallbackInfo&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Isolate&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetIsolate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nl"&gt;tail_recurse_21&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg_22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Number&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ftpl_24&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;FunctionTemplate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_23&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ftpl_24&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetFunction&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;fn_23&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;SetName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NewFromUtf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;fib&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_25&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg_22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_26&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_23&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg_27&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_26&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_28&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;::&lt;/span&gt;&lt;span class="n"&gt;Cast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;GetCurrentContext&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Global&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NewFromUtf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;console&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;NewFromUtf8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;log&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_29&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;arg_27&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;result_30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fn_28&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;isolate&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;argv_29&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;result_30&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Local&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;NODE_SET_METHOD&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;jsc_main&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jsc_main&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;NODE_MODULE&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NODE_GYP_MODULE_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Init&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let's time this version:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;build/recursion.js
&lt;span class="m"&gt;6765&lt;/span&gt;
node&lt;span class="w"&gt; &lt;/span&gt;build/recursion.js&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.16s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.03s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;107&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.175&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;jsc, over twice as slow, is already falling behind Node. :)&lt;/p&gt;
&lt;p&gt;As I incremented the number passed to my fibonacci function the
compiled program time to completion get exponentially worse. Node
stayed the same. I decided to try tail-call optimization to decrease
the performance distance between Node and jsc.&lt;/p&gt;
&lt;p&gt;I implemented tail-call optimization for the interpreter in BSDScheme
by putting all functions in a loop that would break if tail-call
elimination was not to happen. It took me a week to implement this and
I never put it in place for the compiler. This time around I was able
to add basic tail call elimination to jsc in two hours. It is done
by &lt;code&gt;label&lt;/code&gt;s and &lt;code&gt;goto&lt;/code&gt;s instead of a tail call
when applicable.&lt;/p&gt;
&lt;p&gt;Here is a tail-call optimized version of the same program
(example/tco.js):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We add a call to &lt;code&gt;main()&lt;/code&gt; again for Node and time it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;example/tco.js
&lt;span class="m"&gt;12586269025&lt;/span&gt;
node&lt;span class="w"&gt; &lt;/span&gt;example/tco.js&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.06s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.02s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;96&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.080&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And compile it with jsc and time it:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;jsc&lt;span class="w"&gt; &lt;/span&gt;example/tco.js
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;time&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="w"&gt; &lt;/span&gt;build/tco.js
&lt;span class="m"&gt;12586269025&lt;/span&gt;
node&lt;span class="w"&gt; &lt;/span&gt;build/tco.js&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.07s&lt;span class="w"&gt; &lt;/span&gt;user&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.02s&lt;span class="w"&gt; &lt;/span&gt;system&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;95&lt;/span&gt;%&lt;span class="w"&gt; &lt;/span&gt;cpu&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;.087&lt;span class="w"&gt; &lt;/span&gt;total
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Well that's not bad at all. :)&lt;/p&gt;
&lt;h3 id="next-steps-with-jsc"&gt;Next steps with jsc&lt;/h3&gt;&lt;p&gt;jsc has very limited support for... everything. Today I added almost
all primitive numeric operations + equality/inequality operations +
unit tests. jsc does not yet support nested functions, callbacks, or
closures. It supports &lt;code&gt;while&lt;/code&gt; loops but not
yet &lt;code&gt;for&lt;/code&gt; loops. And I'm not sure if it supports &lt;code&gt;else
if&lt;/code&gt;. It does not support arrays or objects let alone
constructors and prototypes. Adding support for these is low-hanging
fruit.&lt;/p&gt;
&lt;p&gt;After the low-hanging fruit, more interesting projects for jsc include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generating C++ with embedded V8 rather than only targeting Node addons&lt;/li&gt;
&lt;li&gt;type inference or type hinting for generating unboxed functions a la Cython and SBCL&lt;/li&gt;
&lt;/ul&gt;</description><author>Notes on software development</author><pubDate>Sun, 02 Sep 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/compiling-dynamic-programming-languages.html</guid></item><item><title>Sloc Cloc and Code Revisited - A focus on accuracy</title><link>https://boyter.org/posts/sloc-cloc-code-revisited/</link><description>&lt;p&gt;&lt;strong&gt;Update 2019-03-13&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is now part of a series of blog posts about &lt;code&gt;scc&lt;/code&gt; Sloc Cloc and Code which has now been optimised to be the fastest code counter for almost every workload. Read more about it at the following links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;Sloc Cloc and Code - What happened on the way to faster Cloc 2018-04-16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-revisited/"&gt;Sloc Cloc and Code Revisited - A focus on accuracy 2018-08-28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance/"&gt;Sloc Cloc and Code Revisited - Optimizing an already fast Go application 2018-09-19&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance-update/"&gt;Sloc Cloc and Code a Performance Update 2019-01-09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-badges/"&gt;Sloc Cloc and Code Badges for Github/Bitbucket/Gitlab&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Two things prompted me to start looking at my code counter &lt;code&gt;scc&lt;/code&gt; again. The first being the release of Go 1.11. New releases of compilers, libraries and tool-chains have a wonderful habit of making things go faster without you having to do anything other than recompile. In addition they often provide new methods which assist with this and are worth exploring.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Tue, 28 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/sloc-cloc-code-revisited/</guid></item><item><title>Reading files quickly in Rust</title><link>https://boyter.org/posts/reading-files-quickly-in-rust/</link><description>&lt;p&gt;I have been wanting to learn Rust for a while now. I did play with it some time back &lt;a href="https://boyter.org/2017/09/working-rust/"&gt;https://boyter.org/2017/09/working-rust/&lt;/a&gt; for solving some of the project Euler problems and was reasonably impressed with how it turned out. However as I had no practical use for it at the time I ended up investing more time in Go.&lt;/p&gt;
&lt;p&gt;Go as it turns out is a pretty decent language, and somewhat akin to Python in terms of getting things done. There is usually one obvious way to solve any problem. I was even very happy with the performance I was getting out of it. As such I took on building the fastest version of a count lines of code program I could using Go &lt;code&gt;scc&lt;/code&gt; which you can read about at &lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;sloc cloc and code&lt;/a&gt;.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 20 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/reading-files-quickly-in-rust/</guid></item><item><title>A records on top level domains</title><link>https://captnemo.in/blog/2018/08/18/tld-a-records/</link><description>&lt;p&gt;A few more changes since &lt;a href="/blog/2018/06/02/google-tld-no-more-a-records/"&gt;the last time I ran this&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: An automatically updated version of this is available at https://captnemo.in/tld-a-record/&lt;/p&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;TLD&lt;/td&gt;
      &lt;td&gt;IP&lt;/td&gt;
      &lt;td&gt;Web&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ai&lt;/td&gt;
      &lt;td&gt;209.59.119.34&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://ai"&gt;http&lt;/a&gt;] [&lt;a href="https://ai"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;arab&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://arab"&gt;http&lt;/a&gt;] [&lt;a href="https://arab"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;bh&lt;/td&gt;
      &lt;td&gt;88.201.27.211&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://bh"&gt;http&lt;/a&gt;] [&lt;a href="https://bh"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;charity&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://charity"&gt;http&lt;/a&gt;] [&lt;a href="https://charity"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;cm&lt;/td&gt;
      &lt;td&gt;195.24.205.60&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://cm"&gt;http&lt;/a&gt;] [&lt;a href="https://cm"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dk&lt;/td&gt;
      &lt;td&gt;193.163.102.58&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://dk"&gt;http&lt;/a&gt;] [&lt;a href="https://dk"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;gg&lt;/td&gt;
      &lt;td&gt;87.117.196.80&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://gg"&gt;http&lt;/a&gt;] [&lt;a href="https://gg"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;inc&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://inc"&gt;http&lt;/a&gt;] [&lt;a href="https://inc"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;je&lt;/td&gt;
      &lt;td&gt;87.117.196.80&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://je"&gt;http&lt;/a&gt;] [&lt;a href="https://je"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pa&lt;/td&gt;
      &lt;td&gt;168.77.8.43&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://pa"&gt;http&lt;/a&gt;] [&lt;a href="https://pa"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pn&lt;/td&gt;
      &lt;td&gt;80.68.93.100&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://pn"&gt;http&lt;/a&gt;] [&lt;a href="https://pn"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;politie&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://politie"&gt;http&lt;/a&gt;] [&lt;a href="https://politie"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;tk&lt;/td&gt;
      &lt;td&gt;217.119.57.22&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://tk"&gt;http&lt;/a&gt;] [&lt;a href="https://tk"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;uz&lt;/td&gt;
      &lt;td&gt;91.212.89.8&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://uz"&gt;http&lt;/a&gt;] [&lt;a href="https://uz"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ws&lt;/td&gt;
      &lt;td&gt;64.70.19.33&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://ws"&gt;http&lt;/a&gt;] [&lt;a href="https://ws"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;202.170.80.40&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://мон"&gt;http&lt;/a&gt;] [&lt;a href="https://мон"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;218.100.84.27&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://мон"&gt;http&lt;/a&gt;] [&lt;a href="https://мон"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;180.149.98.78&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://мон"&gt;http&lt;/a&gt;] [&lt;a href="https://мон"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;政府&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://政府"&gt;http&lt;/a&gt;] [&lt;a href="https://政府"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;عرب&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;[&lt;a href="http://عرب"&gt;http&lt;/a&gt;] [&lt;a href="https://عرب"&gt;https&lt;/a&gt;]&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Diff:&lt;/p&gt;

&lt;div class="language-diff highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="gi"&gt;+bh
+charity
&lt;/span&gt;&lt;span class="gd"&gt;-etisalat
&lt;/span&gt;&lt;span class="gi"&gt;+inc
&lt;/span&gt;&lt;span class="gd"&gt;-اتصالات
-招聘
&lt;/span&gt; 政府
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</description><author>Nemo's Home</author><pubDate>Sat, 18 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/08/18/tld-a-records/</guid></item><item><title>Fetchr Data Science Infra at 1 year</title><link>https://bytepawn.com/fetchr-data-science-infra.html</link><description>&lt;p&gt;A description of our Analytics+ML cluster running on AWS, using Presto, Airflow and Superset.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Fetchr Data Science Infra" src="/images/fetchr-data-science-infra-update.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Tue, 14 Aug 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/fetchr-data-science-infra.html</guid></item><item><title>btest: a language agnostic test runner</title><link>http://notes.eatonphil.com/btest-a-language-agnostic-test-runner.html</link><description>&lt;p&gt;&lt;a href="https://github.com/briansteffens/btest"&gt;btest&lt;/a&gt; is a minimal,
language-agnostic test runner originally written for testing
compilers. Brian, an ex- co-worker from Linode, wrote the first
implementation in &lt;a href="https://crystal-lang.org/"&gt;Crystal&lt;/a&gt; (a compiled
language clone of Ruby) for testing
&lt;a href="https://github.com/briansteffens/bshift"&gt;bshift&lt;/a&gt;, a compiler
project. The tool accomplished exactly what I needed for my own
language project, &lt;a href="https://github.com/eatonphil/bsdscheme"&gt;BSDScheme&lt;/a&gt;,
and had very few dependencies. After some issues with Crystal support
in containerized CI environments, and despite some incredible
&lt;a href="https://github.com/briansteffens/btest/pull/5"&gt;assistance from&lt;/a&gt; &lt;a href="https://github.com/briansteffens/btest/pull/4"&gt;the
Crystal community&lt;/a&gt;, we
rewrote btest in D to simplify downstream use.&lt;/p&gt;
&lt;h3 id="how-it-works"&gt;How it works&lt;/h3&gt;&lt;p&gt;btest registers a command (or commands) to run and verifies the
command output and status for different inputs. btest iterates over
files in a directory to discover test groups and individual tests
within. It supports a limited template language for easily adjusting a
more-or-less similar set of tests. And it supports running test groups
and individual tests themselves in parallel. All of this is managed
via a simple YAML config.&lt;/p&gt;
&lt;h3 id="btest.yaml"&gt;btest.yaml&lt;/h3&gt;&lt;p&gt;btest requires a project-level configuration file to declare the test
directory, the command(s) to run per test, etc. Let's say we want to
run tests against a python program. We create
a &lt;code&gt;btest.yaml&lt;/code&gt; file with the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;test_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tests&lt;/span&gt;

&lt;span class="nt"&gt;runners&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Run tests with cpython&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;python test.py&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;code&gt;test_path&lt;/code&gt; is the directory in which tests are located.
&lt;code&gt;runners&lt;/code&gt; is an array of commands to run per test. We
hard-code a file to run &lt;code&gt;test.py&lt;/code&gt; as a project-level
standard file that will get written to disk in an appropriate path for
each test-case.&lt;/p&gt;
&lt;h4 id="on-multiple-runners"&gt;On multiple runners&lt;/h4&gt;&lt;p&gt;Using multiple runners is helpful when we want to run all tests with
different test commands or test command settings. For instance, we
could run tests against cpython and pypy by adding another runner to
the runners section.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;test_path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tests&lt;/span&gt;

&lt;span class="nt"&gt;runners&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Run tests with cpython&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;python test.py&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Run tests with pypy&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;pypy test.py&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="an-example-test-config"&gt;An example test config&lt;/h3&gt;&lt;p&gt;Let's create a &lt;code&gt;divide-by-zero.yaml&lt;/code&gt; file in
the &lt;code&gt;tests&lt;/code&gt; directory and add the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nt"&gt;cases&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Should exit on divide by zero&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="no"&gt;File &amp;quot;test.py&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="no"&gt;4 / 0&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;ZeroDivisionError: division by zero&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;denominator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;0&lt;/span&gt;
&lt;span class="nt"&gt;templates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;test.py&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p p-Indicator"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="no"&gt;4 / {{ denominator }}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this example, &lt;code&gt;name&lt;/code&gt; will be printed out when the test
is run. &lt;code&gt;status&lt;/code&gt; is the expected integer returned by
running the program. &lt;code&gt;stdout&lt;/code&gt; is the entire expected output
written by the program during execution. None of these three fields
are required. If &lt;code&gt;status&lt;/code&gt; or stdout are not
provided, btest will skip checking them.&lt;/p&gt;
&lt;p&gt;Any additional key-value pairs are treated as template variable values
and will be substituted if/where it is referenced in the templates
section when the case is run. &lt;code&gt;denominator&lt;/code&gt; is the only
such variable we use in this example. When this first (and only) case
is run, &lt;code&gt;test.py&lt;/code&gt; will be written to disk
containing &lt;code&gt;4 / 0&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id="templates-section"&gt;templates section&lt;/h4&gt;&lt;p&gt;The &lt;code&gt;templates&lt;/code&gt; section is a dictionary allowing us to
specify files to be created with variable substitution. All files are
created in the same directory per test case, so if we want to import
code we can do so with relative paths.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/eatonphil/bsdscheme/blob/master/tests/include.yaml"&gt;Here&lt;/a&gt;
is a simple example of a BSDScheme test that uses this feature.&lt;/p&gt;
&lt;h3 id="running-btest"&gt;Running btest&lt;/h3&gt;&lt;p&gt;Run btest from the root directory (the directory
above &lt;code&gt;tests&lt;/code&gt;) and we'll see all the grouped test cases
that btest registers and the result of each test:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;zero&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yaml&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;PASS&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Should&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;exit&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;divide&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;zero&lt;/span&gt;

&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;passed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cpython&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="use-in-ci-environments"&gt;Use in CI environments&lt;/h3&gt;&lt;p&gt;In the future we may provide pre-built release binaries. But in the
meantime, the CI step involves downloading git and ldc and
building/installing btest before calling it.&lt;/p&gt;
&lt;h4 id="circle-ci"&gt;Circle CI&lt;/h4&gt;&lt;p&gt;This is the
&lt;a href="https://github.com/eatonphil/bsdscheme/blob/master/.circleci/config.yml"&gt;config&lt;/a&gt;
file I use for testing BSDScheme:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;jobs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dlanguage&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ldc&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;steps&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;checkout&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;debian&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;packaged&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;essential&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ldc2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sr"&gt;/usr/local/bin/&lt;/span&gt;&lt;span class="n"&gt;ldc&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;com&lt;/span&gt;&lt;span class="sr"&gt;/briansteffens/&lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bsdscheme&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bsdscheme&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="travis-ci"&gt;Travis CI&lt;/h4&gt;&lt;p&gt;This is the
&lt;a href="https://github.com/briansteffens/bshift/blob/master/.travis.yml"&gt;config&lt;/a&gt;
Brian uses for testing BShift:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;required&lt;/span&gt;

&lt;span class="n"&gt;language&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;

&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ldc&lt;/span&gt;

&lt;span class="n"&gt;script&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ldc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gets&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;installed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sometimes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;which&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$DC&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="sr"&gt;/usr/local/bin/&lt;/span&gt;&lt;span class="n"&gt;ldc&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bshift&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$PWD&lt;/span&gt;&lt;span class="sr"&gt;/bin/bshift /usr/local/bin/&lt;/span&gt;&lt;span class="n"&gt;bshift&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$PWD&lt;/span&gt;&lt;span class="sr"&gt;/lib /usr/local/lib/&lt;/span&gt;&lt;span class="n"&gt;bshift&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nasm&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;apt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nasm&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basm&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;com&lt;/span&gt;&lt;span class="sr"&gt;/briansteffens/&lt;/span&gt;&lt;span class="n"&gt;basm&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;basm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cabal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ln&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;$PWD&lt;/span&gt;&lt;span class="sr"&gt;/basm/dist/build/basm/basm /usr/local/bin/&lt;/span&gt;&lt;span class="n"&gt;basm&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;clone&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="o"&gt;://&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;com&lt;/span&gt;&lt;span class="sr"&gt;/briansteffens/&lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;btest&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;</description><author>Notes on software development</author><pubDate>Sat, 04 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/btest-a-language-agnostic-test-runner.html</guid></item><item><title>Queryset.explain() released in Django 2.1</title><link>https://tomforb.es/blog/queryset-explain-released-in-django/</link><description>While working on any large-ish Django project you are bound to come across a slow query that’s perhaps missing an index or doing something else expensive. My workflow for diagnosing this was to get the query that is being executed ( str(queryset.query) ) and paste it into a database shell, prefixing...</description><author>Tom Forbes</author><pubDate>Wed, 01 Aug 2018 22:29:29 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/queryset-explain-released-in-django/</guid></item><item><title>Singapore H1B1 Tips</title><link>https://www.swyx.io/h1b1</link><description>&lt;h2&gt;much of the original piece below is outdated. this is my remaining 2023 updates for fellow singaporeans.&lt;/h2&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 01 Aug 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/h1b1</guid></item><item><title>Repeating History with Elixir...again</title><link>https://www.brightball.com/articles/repeating-history-with-elixir-again</link><description>Over the weekend I got the chance to speak at the inaugural Carolina Code Conf in Greenville, SC. It's the upstate polyglot conference where just about any relevant subject is welcome, so I submitted a talk on Elixir. I also gave a lightning talk on DMARC thanks to our wonderful sponsor, dmarcian.</description><author>Brightball Articles</author><pubDate>Tue, 31 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/repeating-history-with-elixir-again</guid></item><item><title>Run youtube-dl (or similar) in the background</title><link>https://smcleod.net/2018/07/run-youtube-dl-or-similar-in-the-background/</link><description>&lt;p&gt;I wanted an alias or function to use &lt;a href="https://rg3.github.io/youtube-dl/"&gt;&lt;code&gt;youtube-dl&lt;/code&gt;&lt;/a&gt; in the background.
Looking around the web lots of people seemed to want this and most of them were banging their heads against a wall due to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A) bash quoting&lt;/li&gt;
&lt;li&gt;B) backgrounding dying when their terminal closed&lt;/li&gt;
&lt;li&gt;C) passing the argument (url in my case) to the function&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s a simple function I whipped up that seems to &amp;lsquo;just works&amp;rsquo;™:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;function&lt;/span&gt; yt
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;  nohup youtube-dl &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; --no-progress 2&amp;gt;&lt;span class="p"&gt;&amp;amp;&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &amp;gt; youtube-dl-&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;date +%Y%m%d-%H%M%S&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;.log &lt;span class="p"&gt;&amp;amp;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And if you don&amp;rsquo;t want logs, simply send the output to &lt;code&gt;/dev/null&lt;/code&gt;:&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Mon, 30 Jul 2018 11:52:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/07/run-youtube-dl-or-similar-in-the-background/</guid></item><item><title>Phishing Leaves a DMARC Trail</title><link>https://www.brightball.com/articles/phishing-thats-gonna-leave-a-dmarc</link><description>In May I had the opportunity to present at the Anti-Phishing Working Group (APWG) Conference after spending some time cross referencing the APWG's eCrime Exchange data with dmarcian's historic DMARC reports to see if we could identify consistent patterns among known bad actors, as well as potentially identifying a wider scope to the attacks that any single entity could see. The results were interesting!</description><author>Brightball Articles</author><pubDate>Tue, 24 Jul 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/phishing-thats-gonna-leave-a-dmarc</guid></item><item><title>What not to spend time on</title><link>https://bytepawn.com/what-not-to-spend-time-on.html</link><description>&lt;p&gt;Warren Buffett says deciding what &lt;strong&gt;not&lt;/strong&gt; to spend time on is just as important as deciding what to spend time on.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Warren Buffett" src="/images/warren-buffett.jpg" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Mon, 23 Jul 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/what-not-to-spend-time-on.html</guid></item><item><title>Disabling scroll-wheel zoom in Firefox</title><link>https://smcleod.net/2018/07/disabling-scroll-wheel-zoom-in-firefox/</link><description>&lt;p&gt;This feature annoys me endlessly, I end up zoomed in and out of websites all over the internet.
&amp;hellip; But the fix is easy and there&amp;rsquo;s no addons required.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Navigate to &lt;code&gt;about:config&lt;/code&gt; (in Firefox&amp;rsquo;s URL bar)&lt;/li&gt;
&lt;li&gt;Change the value of the following two properties to &lt;code&gt;0&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight"&gt;&lt;pre class="chroma" tabindex="0"&gt;&lt;code class="language-fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mousewheel.with_control.action
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mousewheel.with_meta.action
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If you use Firefox sync and want these settings to sync between your machines, also add the following properties:&lt;/p&gt;
&lt;p&gt;Create two &lt;em&gt;new&lt;/em&gt; properties both of type &lt;code&gt;boolean&lt;/code&gt; and set them to &lt;code&gt;true&lt;/code&gt;:&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Mon, 16 Jul 2018 13:57:14 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/07/disabling-scroll-wheel-zoom-in-firefox/</guid></item><item><title>Beat the averages</title><link>https://bytepawn.com/beat-the-averages.html</link><description>&lt;p&gt;When working with averages, we have to be careful. There are pitfalls lurking to pollute our statistics and results reported.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Probability distribution" src="/images/averages-7.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Sat, 07 Jul 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/beat-the-averages.html</guid></item><item><title>Thanks Economist, You Really Know What Has Gone Wrong with the Internet</title><link>https://svedic.org/programming/thanks-economist-fix-the-internet</link><description>UPDATE: Reddit 1: r/web_design discussion Reddit 2: r/ProgrammerHumor discussion HackerNews discussion I was surprised that there are actually some quite interesting views and proposals in the discussions above. If you liked this, you are probably going to like my article &amp;#8230; &lt;a href="https://svedic.org/programming/thanks-economist-fix-the-internet"&gt;Continue reading &lt;span class="meta-nav"&gt;&amp;#8594;&lt;/span&gt;&lt;/a&gt;</description><author>Svedic.org</author><pubDate>Wed, 04 Jul 2018 13:38:00 GMT</pubDate><guid isPermaLink="true">https://svedic.org/programming/thanks-economist-fix-the-internet</guid></item><item><title>A Glance through Docusaurus, Docz, and React-Static</title><link>https://www.swyx.io/a-glance-through-docusaurus-docz-and-react-static-47in</link><description>&lt;p&gt;a survey of new documentation/static site generators&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 30 Jun 2018 05:18:35 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/a-glance-through-docusaurus-docz-and-react-static-47in</guid></item><item><title>PostgresOpen 2018 - First look at talks</title><link>/2018/06/27/postgresopen-talk-list/</link><description>&lt;p&gt;&lt;a href="https://2018.postgresopen.org/"&gt;PostgresOpen&lt;/a&gt; is just a few months away and our &lt;a href="https://postgresql.us/events/pgopen2018/sessions/"&gt;list of talks&lt;/a&gt; is now live and available on the PostgresOpen website. This year selecting the talks was the hardest yet not only due to the number of talk submissions, but also the across the board high quality of submissions. There is hopefully something for everyone among the talks, at least if you like Postgres that is.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re thinking about joining us I&amp;rsquo;d love to see you there and buy you a beer or coffee. The conference is September 5-7 in downtown San Francisco, and early bird tickets are open for just another few weeks. If you want to save some money on &lt;a href="https://2018.postgresopen.org/tickets/"&gt;tickets grab it&lt;/a&gt; and the &lt;a href="https://2018.postgresopen.org/venue/"&gt;room&lt;/a&gt; now before things jump.&lt;/p&gt;
&lt;p&gt;But, if you&amp;rsquo;re curious for a sampling of a few of the talks I thought I&amp;rsquo;d break down my top five I&amp;rsquo;m personally most excited about:&lt;/p&gt;
&lt;h3 id="debugging-the-postgres-plannerhttpspostgresqluseventspgopen2018sessionssession551-debugging-the-postgres-planner"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/551-debugging-the-postgres-planner/"&gt;Debugging the Postgres planner&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Okay, this one immediately caught my atttention. Melanie will start with the basics of an explain plan to progress down into an actual bug within the Postgres planner, how to can debug it in Postgres, and then write a patch for a fix herself. This talk is well beyond my depth as I&amp;rsquo;ll likely never contribute code to the Postgres planner, but seems extremely entertaining and likely to highlight both performance profiling as well as useful debugging tips.&lt;/p&gt;
&lt;h3 id="cleaning-out-crocodiles-teeth-with-postgresql-indexeshttpspostgresqluseventspgopen2018sessionssession506-cleaning-out-crocodiles-teeth-with-postgresql-indexes-a-story-on-all-the-index-types-in-pg"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/506-cleaning-out-crocodiles-teeth-with-postgresql-indexes-a-story-on-all-the-index-types-in-pg/"&gt;Cleaning out Crocodiles teeth with PostgreSQL indexes&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I saw Louise give a super practical talk on undertanding explain this year in PgDay Paris. It was both valuable for application developers that aren&amp;rsquo;t Postgres experts as well as surfaced knowledge for those that thought they already understood explain. I&amp;rsquo;m excited to hear her take on indexes, but maybe even more excited for the storytelling that will come along with this talk. A talk that can be put to a story always becomes a bit easier to follow the journey than simply the technical facts.&lt;/p&gt;
&lt;h3 id="how-postgresql-extension-apis-are-changing-the-face-of-relational-databaseshttpspostgresqluseventspgopen2018sessionssession491-how-postgresql-extension-apis-are-changing-the-face-of-relational-databases"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/491-how-postgresql-extension-apis-are-changing-the-face-of-relational-databases/"&gt;How PostgreSQL extension APIs are changing the face of relational databases&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve said it before personally that Postgres is becoming more of a data platform than simply a relational database. Part of that is flexibility towards datatypes and the broad use cases Postgres can support from OLTP, to OLAP, to &lt;a href="https://www.citusdata.com/blog/2018/06/07/what-is-citus-good-for/"&gt;HTAP&lt;/a&gt;. The other big part is extensions! Extensions allow Postgres to continue to advance outside of the standard Postgres core codebase and release cycle. The list of extensions (&lt;a href="https://postgis.net/"&gt;PostGIS&lt;/a&gt;, &lt;a href="https://www.citusdata.com/blog/2017/04/04/distributed_count_distinct_with_postgresql/"&gt;HyperLogLog&lt;/a&gt;, &lt;a href="https://github.com/pgpartman/pg_partman"&gt;pg_partman&lt;/a&gt;, &lt;a href="https://www.citusdata.com"&gt;Citus&lt;/a&gt;) in this talk is pretty great, and curious to hear more on the APIs themselves.&lt;/p&gt;
&lt;h3 id="connection-pooling-101httpspostgresqluseventspgopen2018sessionssession570-connection-pooling-101"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/570-connection-pooling-101/"&gt;Connection Pooling 101&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Okay, connection pooling has been talked about before. Yet, still SO MANY people don&amp;rsquo;t use it in production. Connection pooling can have as large of an impact as understanding explain. In this talk Samantha looks at the pros/cons of connection pooling itself with Postgres, and should provide some good guidance for getting things setup.&lt;/p&gt;
&lt;h3 id="hot---understaning-this-important-optimization-updatehttpspostgresqluseventspgopen2018sessionssession517-hot-understanding-this-important-update-optimization"&gt;
&lt;div&gt;
&lt;a href="https://postgresql.us/events/pgopen2018/sessions/session/517-hot-understanding-this-important-update-optimization/"&gt;HOT - Understaning this important optimization update&lt;/a&gt;
&lt;/div&gt;
&lt;/h3&gt;
&lt;p&gt;Grant&amp;rsquo;s talk last year on tuning Postgres for &lt;a href="https://www.youtube.com/watch?v=xrMbzHdPLKM"&gt;high write workloads&lt;/a&gt; was a great one that covered not only practical tips but some of the details of how things work under the covers. This looks like a great follow-on focusing on heap only tuples and how they can greatly improve things like bloat and overal write throughput.&lt;/p&gt;
&lt;h2 id="see-you-there"&gt;
&lt;div&gt;
See you there
&lt;/div&gt;
&lt;/h2&gt;
&lt;p&gt;If you have any questions about the conference I&amp;rsquo;d be happy to answer them, though hopefully based on the short sampling of talks you have all the reason you need to join us in September.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 27 Jun 2018 23:55:56 GMT</pubDate><guid isPermaLink="true">/2018/06/27/postgresopen-talk-list/</guid></item><item><title>Specialize In The New</title><link>https://www.swyx.io/specialize-in-the-new</link><description>&lt;blockquote&gt;
&lt;p&gt;Author's note: This is part 4 of a series of essays I originally drafted about &lt;a href="https://gist.github.com/sw-yx/9720bd4a30606ca3ffb8d407113c0fe5"&gt;Opinions for your Tech Career&lt;/a&gt;. Part 1 is &lt;a href="https://www.swyx.io/learn-in-public/"&gt;Learn in Public&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description><author>swyx's site RSS Feed</author><pubDate>Fri, 22 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/specialize-in-the-new</guid></item><item><title>Clone Open Source Apps</title><link>https://www.swyx.io/clone-open-source-apps</link><description>&lt;blockquote&gt;
&lt;p&gt;Author's note: This is part 3 of a series of essays I originally drafted about &lt;a href="https://gist.github.com/sw-yx/9720bd4a30606ca3ffb8d407113c0fe5"&gt;Opinions for your Tech Career&lt;/a&gt;. Part 1 is &lt;a href="https://www.swyx.io/learn-in-public/"&gt;Learn in Public&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description><author>swyx's site RSS Feed</author><pubDate>Thu, 21 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/clone-open-source-apps</guid></item><item><title>Anonymous PPK With NaCl</title><link>https://rjp.is/blogging/posts/anonymous-ppk-with-nacl/</link><description>In which we seal some boxes with NaCl.</description><author>infrequent oscillations</author><pubDate>Wed, 20 Jun 2018 16:22:25 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/anonymous-ppk-with-nacl/</guid></item><item><title>An OOP Problem</title><link>https://rjp.is/blogging/posts/an-oop-problem/</link><description>In which we flail about, object-orientedly.</description><author>infrequent oscillations</author><pubDate>Wed, 20 Jun 2018 14:15:54 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/an-oop-problem/</guid></item><item><title>Know Your Tools</title><link>https://www.swyx.io/know-your-tools</link><description>&lt;blockquote&gt;
&lt;p&gt;Author's note: This is part 2 of a series of essays I originally drafted about &lt;a href="https://gist.github.com/sw-yx/9720bd4a30606ca3ffb8d407113c0fe5"&gt;Opinions for your Tech Career&lt;/a&gt;. Part 1 is &lt;a href="https://www.swyx.io/learn-in-public/"&gt;Learn in Public&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 20 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/know-your-tools</guid></item><item><title>Learn In Public</title><link>https://www.swyx.io/learn-in-public</link><description>&lt;p&gt;The fastest way to build your expertise, network, and second brain.&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Tue, 19 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/learn-in-public</guid></item><item><title>Is Coding Style Important?</title><link>https://cmdev.com/blog/2018-06-18-codingstyle/</link><description>Have a style, any style</description><author>The Cranky Developer on Crater Moon Development</author><pubDate>Mon, 18 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://cmdev.com/blog/2018-06-18-codingstyle/</guid></item><item><title>Why count lines of code?</title><link>https://boyter.org/posts/why-count-lines-of-code/</link><description>&lt;p&gt;A work colleague (let&amp;rsquo;s call him Owen as that&amp;rsquo;s his name) asked me the other day&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;ldquo;I dont understand the problem space &lt;code&gt;scc&lt;/code&gt; et al solve. If you wanted to write a short post, i&amp;rsquo;d read and share the hell out of it. Basically, it seems like a heap of people can see the need for it, and I&amp;rsquo;m trying to understand it myself&amp;rdquo;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Owen is one of the more switched on people I know. As such if he is asking whats the point of tools such as scc, tokei, sloccount, cloc, loc and gocloc then I suspect quite a few other people are asking the same thing.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 11 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/why-count-lines-of-code/</guid></item><item><title>Google owned TLDs don't have A records any more</title><link>https://captnemo.in/blog/2018/06/02/google-tld-no-more-a-records/</link><description>&lt;p&gt;A little while ago (Jan 2018), I ran a scan to see which all TLDs have an A record set (on the TLD). This is what lets you visit &lt;a href="http://ai/"&gt;http://ai/&lt;/a&gt; as a valid website on your browser, for eg.&lt;/p&gt;

&lt;p&gt;I ran the same scan as http://blog.towo.eu/a-records-on-top-level-domains/ (link is down, &lt;a href="https://web.archive.org/web/*/http://blog.towo.eu/a-records-on-top-level-domains/"&gt;archived&lt;/a&gt;) and the results are at &lt;a href="https://captnemo.in/blog/2018/02/09/tld-a-records/"&gt;https://captnemo.in/blog/2018/02/09/tld-a-records/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Decided to re-run the scan today, and noticed a stark difference: A lot of Google-owned TLD’s which were earlier pointing to &lt;code class="language-plaintext highlighter-rouge"&gt;127.0.53.53&lt;/code&gt; don’t have a A record anymore.&lt;/p&gt;

&lt;p&gt;Scan run from &lt;code class="language-plaintext highlighter-rouge"&gt;AS45609&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Results:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;TLD&lt;/th&gt;
      &lt;th&gt;IP&lt;/th&gt;
      &lt;th&gt;Web&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ai&lt;/td&gt;
      &lt;td&gt;209.59.119.34&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://ai"&gt;[http]&lt;/a&gt;, &lt;a href="https://ai"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;arab&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;Private IP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;cm&lt;/td&gt;
      &lt;td&gt;195.24.205.60&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://cm"&gt;[http]&lt;/a&gt;, &lt;a href="https://cm"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dk&lt;/td&gt;
      &lt;td&gt;193.163.102.58&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://dk"&gt;[http]&lt;/a&gt;, &lt;a href="https://dk"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;etisalat&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;Private IP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;gg&lt;/td&gt;
      &lt;td&gt;87.117.196.80&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://gg"&gt;[http]&lt;/a&gt;, &lt;a href="https://gg"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;je&lt;/td&gt;
      &lt;td&gt;87.117.196.80&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://je"&gt;[http]&lt;/a&gt;, &lt;a href="https://je"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pa&lt;/td&gt;
      &lt;td&gt;168.77.8.43&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://pa"&gt;[http]&lt;/a&gt;, &lt;a href="https://pa"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pn&lt;/td&gt;
      &lt;td&gt;80.68.93.100&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://pn"&gt;[http]&lt;/a&gt;, &lt;a href="https://pn"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;politie&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;Private IP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;tk&lt;/td&gt;
      &lt;td&gt;217.119.57.22&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://tk"&gt;[http]&lt;/a&gt;, &lt;a href="https://tk"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;uz&lt;/td&gt;
      &lt;td&gt;91.212.89.8&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://uz"&gt;[http]&lt;/a&gt;, &lt;a href="https://uz"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ws&lt;/td&gt;
      &lt;td&gt;64.70.19.33&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://ws"&gt;[http]&lt;/a&gt;, &lt;a href="https://ws"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;218.100.84.27&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://мон"&gt;[http]&lt;/a&gt;, &lt;a href="https://мон"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;202.170.80.40&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://мон"&gt;[http]&lt;/a&gt;, &lt;a href="https://мон"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;180.149.98.78&lt;/td&gt;
      &lt;td&gt;&lt;a href="http://мон"&gt;[http]&lt;/a&gt;, &lt;a href="https://мон"&gt;[https]&lt;/a&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;اتصالات&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;Private IP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;政府&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;Private IP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;عرب&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;Private IP&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;招聘&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
      &lt;td&gt;Private IP&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Comparing with the previous scan, these TLDs no longer have an A record with them:&lt;/p&gt;

&lt;div class="language-diff highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="gd"&gt;-android
-cal
-chrome
-dclk
-drive
-gle
-guge
-hangout
-nexus
-play
-sport
-谷歌
-グーグル
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The majority of these are owned by Google. Not claiming it means anything, just a nice observation.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: An automatically updated version of this is available at https://captnemo.in/tld-a-record/&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Sat, 02 Jun 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/06/02/google-tld-no-more-a-records/</guid></item><item><title>How to securely wipe an NVMe drive</title><link>http://blog.pythonaro.com/2018/05/how-to-securely-wipe-nvme-drive.html</link><description>NVMe drives are great: they are fast and they are huge. That huge size, however, can be a pain when it comes to securely erasing data. Old-school commands like &lt;code&gt;wipe&lt;/code&gt; are simply not up to the task; and even if they were, they work on assumptions that do not map properly to a solid-state world. Writing random data over and over is going to dramatically reduce the lifespan of a solid-state drive, and it's pointless when all NVMe disks already have built-in tools that can take care of this task quickly and safely.&lt;br /&gt;
&lt;br /&gt;
So what do you do when you want to wipe a NVMe drive? &lt;br /&gt;
&lt;ol&gt;&lt;li&gt;
Download a recent Linux distribution. I would recommend Debian/Ubuntu or one of their smaller derivatives (like Knoppix). Burn it on a cdrom or USB drive and boot the system from it.&lt;/li&gt;&lt;li&gt;Make sure your package manager is up-to-date (under Debian/Ubuntu, &lt;code&gt;sudo apt-get update&lt;/code&gt;), then install &lt;code&gt;nvme-cli&lt;/code&gt; (&lt;code&gt;sudo apt-get install nvme-cli&lt;/code&gt;)&lt;/li&gt;&lt;li&gt;If your drive is a Samsung, it now has to be put to sleep (you can do that with &lt;code&gt;sudo systemctl suspend&lt;/code&gt;) and then woken up. This is a weird bug that &lt;a href="https://github.com/linux-nvme/nvme-cli/issues/84"&gt;Samsung doesn't seem in any hurry to fix&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Now you can securely wipe the disk: &lt;code&gt;sudo nvme format -s1 /dev/nvme0n1&lt;/code&gt;&lt;/li&gt;&lt;/ol&gt;
For the curious: the -s option triggers &lt;b&gt;Secure Erase&lt;/b&gt; mode, which can be set to 1 (wipe) or 2 (delete encryption keys for encrypted data). 1 looks like the safest option, because it will automatically do what 2 does if it detects that all data is encrypted. Reference &lt;a href="https://www.mankier.com/1/nvme-format"&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;br /&gt;
The latest NVMe specification adds other commands, to scrub every nook and cranny (bus caches etc), but as far as I know they have not been implemented yet.</description><author>Subclassed</author><pubDate>Fri, 25 May 2018 00:04:11 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/05/how-to-securely-wipe-nvme-drive.html</guid></item><item><title>The European Union, explained to geeks</title><link>http://blog.pythonaro.com/2018/03/the-european-union-explained-to-geeks.html</link><description>I've started describing the EU to geek-friends as a set of  services built over decades.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;You need to coordinate energy supplies across the company departments (nations)? We built a service (&lt;a href="https://en.wikipedia.org/wiki/European_Coal_and_Steel_Community"&gt;ECSC&lt;/a&gt;) that does that. Worked great, no more fighting over the last bit of coal!&lt;/li&gt;
&lt;li&gt;Need atomic development? &lt;a href="https://en.wikipedia.org/wiki/European_Atomic_Energy_Community"&gt;EURATOM&lt;/a&gt; service. Worked great, again.&lt;/li&gt;
&lt;li&gt;And so on and so forth...&lt;/li&gt;
&lt;li&gt;At some point somebody said hey, we need a management tool for all this stuff! "&lt;a href="https://en.wikipedia.org/wiki/European_Council"&gt;European Council&lt;/a&gt;" service, with a set of dedicated subthreads for the real work (&lt;a href="https://en.wikipedia.org/wiki/European_Commission"&gt;European Commission&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;But that service will run amok at times, let's add some monitoring and security checks! &lt;a href="https://en.wikipedia.org/wiki/European_Parliament"&gt;EuroParliament&lt;/a&gt; service - took a few rewrites to get right, nobody really likes to work on monitoring tools; but like systemd on Linux, the EP service should eventually take over anything that talks to real world I/O, so it's pretty important.&lt;/li&gt;
&lt;li&gt;Now all this stuff needs to communicate, with common formats that avoid parsing and reparsing umpteen different types of data back and forth, and ways to look up the right service for a given job - so we created a "CommonMarket SDK", optionally turbocharged with options like &lt;a href="https://en.wikipedia.org/wiki/Schengen_Area"&gt;Schengen&lt;/a&gt;. When exceptions are thrown, the SDK will automatically invoke the &lt;a href="https://en.wikipedia.org/wiki/European_Court_of_Justice"&gt;ECJ&lt;/a&gt; service to resolve matters; and it will self-update by talking to the management services. Once everyone adopts the SDK, then it should be easier to make more radical changes through that (ECB, Euro, common fiscal policy...). But in the end nobody likes change, it's always hard to break backward-compatibility.&lt;/li&gt;
&lt;/ul&gt;
Now, across the company/continent, various departments/nations have adopted some or all of these services, but most of them ended up relying on the SDK one way or the other, so it became basically mandatory. At one point we had to give a name to the whole framework, and "EU" it was.&lt;br /&gt;
It's definitely not a monolith, but there are so many moving parts that the management services are now essential. Some departments have renounced their Write access (Iceland, Norway, Switzerland...) and some were never granted that privilege (Turkey); some departments were forced to change their processes to suit the framework (Italy, Greece, the Eastern countries...). Things are still pretty shaky, developers are still very much at work, but it's getting better with time. It's making more and more services possible and even *easy* to bootstrap (EMA, EFSA, Erasmus...). Bugs creep in and out, we keep adding more and more fault-tolerance, the workload is not yet distributed fairly, etc etc; but it's accomplishing some very heavy tasks that are absolutely mission-critical, if we want to keep the company running and competing with the big boys.&lt;br /&gt;
...&lt;br /&gt;
Then, one day, a department said they'd like to go back to pen and paper. Except for a few services, for which they want to hand-craft packets individually, but those services should just assume the data is still as good as before, and never throw exceptions - they will ignore any response from the ECJ service anyway. Some of what their department does depends on another department, which has no intention to go back to pen and paper, but they say they will somehow give them bits and receive paper, without anyone actually doing the transformation, and without any friction at all. And they'd like to retain write access to the management services too, thank you very much, plus veto powers, so nobody can change SDK formats without consulting them.&lt;br /&gt;
Cue facepalming.</description><author>Subclassed</author><pubDate>Thu, 24 May 2018 09:43:09 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/03/the-european-union-explained-to-geeks.html</guid></item><item><title>Windows Survival Kit for OSX exiles</title><link>http://blog.pythonaro.com/2018/01/windows-survival-kit-for-osx-exiles.html</link><description>After 5 long years, I was gently forced back to Windows for everyday work. The experience has been less terrible than I thought, but was pretty frustrating at the beginning.&lt;br /&gt;
To help anyone in the same predicament, I put together a small list of tips to make the move a bit more tolerable.&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Windows does not have hot corners. Hello, 1995! Anyway, the solution here is using a small app called, unsurprisingly, &lt;a href="https://sites.google.com/site/bytecar/home/hotcornersapp" target="_blank"&gt;HotCornersApp&lt;/a&gt;. It works well enough, and it's fine with multiple screens too. Despite the basic website, it's legit and even opensource, you can &lt;a href="https://github.com/bytecar/HotCornersApp" target="_blank"&gt;compile it yourself&lt;/a&gt; (although beware - apparently the very latest updates may not build properly).&lt;/li&gt;
&lt;li&gt;Windows does not do &lt;a href="http://osxdaily.com/2010/07/23/set-up-text-substitution-in-mac-os-x/" target="_blank"&gt;text substitution&lt;/a&gt;, which is one of those things that you don't know how much you love it until they take it away from you. As far as I can see, there is no free utility on Windows to do this, or nothing that actually works well enough. So, I paid for &lt;a href="http://www.16software.com/breevy/" target="_blank"&gt;Breevy&lt;/a&gt;. It feels a bit retro (it looks blurry on high-def screens...), but it works very well and has all sorts of options and special features.&lt;/li&gt;
&lt;li&gt;Windows doesn't really deal well with multi-language support, aka &lt;i&gt;typing accents from a US keyboard&lt;/i&gt;. Sure, you can use US-International, and deal with &lt;code&gt;'&lt;/code&gt; and &lt;code&gt;"&lt;/code&gt; becoming meta-keys, but for a techie/programmer typing those characters on their own more often than accents, it's extremely annoying. The solution was again Breevy: you can define a combo that will not be triggered unless you type a special character afterwards. For example, I defined &lt;code&gt;`e&lt;/code&gt; to become &lt;code&gt;è&lt;/code&gt; after I press Ctrl. It works absolutely everywhere, although it's nowhere as elegant as the OSX popup. Same story for special characters like £ , € etc.&lt;/li&gt;
&lt;ul&gt;
&lt;li&gt;For best results, check if your keyboard supports custom macro. &lt;a href="https://gaming.kinesis-ergo.com/fsedge/" target="_blank"&gt;Mine does&lt;/a&gt;, so I mapped the blank side-keys to accents and so on. After muscle-memory starts kicking in, this solution is actually superior to stock OSX.&lt;/li&gt;
&lt;/ul&gt;
&lt;li&gt;I was not going to reformat my external hard drives to NTFS, which is a pain to use back on OSX; so again I had to pay for &lt;a href="https://www.paragon-software.com/home/hfs-windows/" target="_blank"&gt;Paragon HFS+ for Windows&lt;/a&gt;. The UI is garbage (and does not work properly with multi-monitor setups), but the actual driver seems to work perfectly.&lt;/li&gt;
&lt;li&gt;Microsoft has basic print-to-PDF support. If you need to concatenate documents, &lt;a href="http://www.primopdf.com/" target="_blank"&gt;PrimoPDF&lt;/a&gt; does it, and it's free (do not download the Nitro version). The interface is not great though.&lt;/li&gt;
&lt;li&gt;For the developer types out there who rely on &lt;a href="https://kapeli.com/dash" target="_blank"&gt;Dash&lt;/a&gt;, a good equivalent on Windows is &lt;a href="https://zealdocs.org/" target="_blank"&gt;Zeal&lt;/a&gt;. It supports the same format, even fetching docsets directly from Dash repositories.&lt;/li&gt;
&lt;li&gt;Also for developer/sysadmin types, the Windows equivalent of homebrew is now &lt;a href="https://chocolatey.org/" target="_blank"&gt;Chocolatey&lt;/a&gt;. Whoever came up with that word should give up trying to name things, but the software does work. You can use it to install 7zip (to get the latest beta with proper security patches, &lt;code&gt;choco install 7zip.install --pre -y&lt;/code&gt;) windirstat and so on, it will make it easy to upgrade them when necessary (rather than having through the usual website-download-install dance, just &lt;code&gt;choco upgrade&lt;/code&gt; them all).&lt;/li&gt;
&lt;li&gt;There are quite a few apps that do what &lt;a href="http://fluidapp.com/" target="_blank"&gt;Fluid&lt;/a&gt; does, i.e. making websites into "native" apps. I know, I know, they are aberrations; but I got used to having a few sites (Gmail, Trello, Hangouts...) accessible this way. After a bad experience with WebCatalog (it was working ok, but then it got stuck trying to upgrade itself), I installed &lt;a href="https://github.com/jiahaog/nativefier" target="_blank"&gt;nativefier&lt;/a&gt;. This is again more for the geek types; it requires &lt;a href="https://www.npmjs.com/" target="_blank"&gt;npm&lt;/a&gt; and it's a command-line app with a few quirks.&lt;/li&gt;
&lt;li&gt;UPDATE 1: to get back the "preview on pressing Space" experience, there is a free app called &lt;a href="https://sourceforge.net/projects/ccseer/"&gt;Seer&lt;/a&gt;. You can also pay for a license, but it's not clear what the difference might be, the free app is more than enough for my needs. I had to remove the Ctrl-Alt-S shortcut in Settings in order to make it work properly.&lt;/li&gt;
&lt;/ul&gt;
Did I miss anything? Feel free to suggest other useful tidbits in comments.</description><author>Subclassed</author><pubDate>Thu, 24 May 2018 09:42:01 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/01/windows-survival-kit-for-osx-exiles.html</guid></item><item><title>How to implement custom BotStorage class for Microsoft BotFramework</title><link>http://blog.pythonaro.com/2018/03/how-to-implement-custom-botstorage.html</link><description>Since launch, the MS BotFramework has been changing very rapidly. So rapidly, in fact, that I recently gave up trying to keep up with my handrolled Python, and embraced (sigh) their NodeJS SDK. At least now I won't have to worry when they break stuff, right ?&lt;br /&gt;
One of the most recent BF changes is the deprecation and eventual removal of the default persistence API. You are now supposed to either use one of the pre-built Azure services (paying $$), or provide your own implementation. In pure Microsoft style, they state that rolling your own is very easy... but never actually provide a sample or even tell you which interface should be implemented.&lt;br /&gt;
I had to scavenge through their code to figure it out (at least they opensource their stuff these days), but I thought I'd save others a bit of aggravation, and here it is:&lt;br /&gt;
&lt;pre&gt;var MyBotStorage = (function () {
    
    // optional constructor
    function MyBotStorage(options) {
        this.options = options;
    }
    
    MyBotStorage.prototype.getData = function (iBotStorageContext, 
                                                callback){
        // IBotStorageData interface
        var data = {
            userData: {},
            conversationData: {},
            privateConversationData: {}
        };
        // the callback MUST be invoked
        // signature: callback(Error, iBotStorageData )
        callback(null, data);
    }
    
    MyBotStorage.prototype.saveData = function (iBotStorageContext, 
                                                iBotStorageData, 
                                                errorCallback){
        // the callback MUST be invoked
        errorCallback(null);
    }
    
    return MyBotStorage;
}());

var botStorage = new MyBotStorage({});

var bot = new builder.UniversalBot(connector, function (session) {
            // your bot code here
    }).set('storage', botStorage); 
&lt;/pre&gt;
As you can see, it is indeed trivial, once you know how. It's sad that MS somehow, in the haste of deprecating their older interfaces, couldn't find the time to put this sample in their otherwise-extensive documentation. I suspect the fact that Azure is not mentioned anywhere might have something to do with it, but &lt;i&gt;I'm sure&lt;/i&gt; I'm just assuming excessive malice and there is a perfectly-plausible explanation that does not involve greed. Or is there?</description><author>Subclassed</author><pubDate>Thu, 24 May 2018 09:41:39 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/03/how-to-implement-custom-botstorage.html</guid></item><item><title>How to add multiple tags to a Go struct</title><link>https://boyter.org/posts/how-to-add-multiple-tags-to-go-struct/</link><description>&lt;p&gt;I was looking to add multiple tags (the declaration after the struct field) to a struct in Go such that I could have it defined in GORM and in JSON.&lt;/p&gt;
&lt;p&gt;This was much harder to find via any search engine I tried than I would have guessed. The answer thankfully is simple once you know and was provided to me by Josh of &lt;a href="https://boyter.org/2017/03/golang-solution-faster-equivalent-java-solution/"&gt;https://boyter.org/2017/03/golang-solution-faster-equivalent-java-solution/&lt;/a&gt; fame.&lt;/p&gt;
&lt;p&gt;The trick is to define multiple tags but with a space separating them. Easy enough and hopefully this post is found by others with the same issue.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 24 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/how-to-add-multiple-tags-to-go-struct/</guid></item><item><title>Machined Horses</title><link>https://rjp.is/blogging/posts/machined-horses/</link><description>In which we machine-learn horse names.</description><author>infrequent oscillations</author><pubDate>Wed, 23 May 2018 06:16:19 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/machined-horses/</guid></item><item><title>Reality Driven Development</title><link>https://www.brightball.com/articles/reality-driven-development-fixing-project-management-in-software</link><description>Not a lot of people know this about me, but I've almost exited programming at three different times in my career...because I wanted to get into project management at a high level. Ever since my first project management class in grad school, it just made sense to me...but after about 15 years in software it doesn't anymore. Let me explain how to fix it.</description><author>Brightball Articles</author><pubDate>Mon, 21 May 2018 13:11:02 GMT</pubDate><guid isPermaLink="true">https://www.brightball.com/articles/reality-driven-development-fixing-project-management-in-software</guid></item><item><title>Writing to be read</title><link>http://notes.eatonphil.com/writing-to-be-read.html</link><description>&lt;p&gt;There is a common struggle in the writing and maintenance of
documentation, checklists, emails, guides, etc. Each provides immense
value; a document may be the key to an important process. The goal is
to remove barriers -- to encourage understanding and correct
application of what has been noted -- without requiring a change in
the character of the reader. That is, expect reading to be difficult
and people to be lazy. &lt;strong&gt;Don't make things harder for your reader than
need be.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Ignoring imperfections in the &lt;em&gt;ideas&lt;/em&gt; transcribed into writing, there
are a few particular aesthetic approaches I take to (hopefully) make
my notes more effective. These ideas have been influenced by readings
on writing, psychology, and user experience. In particular, I
recommend
&lt;a href="https://amzn.to/2rT0dsE"&gt;On Writing Well&lt;/a&gt;,
&lt;a href="https://amzn.to/2IttNAl"&gt;Thinking Fast and Slow&lt;/a&gt;,
and &lt;a href="https://www.nngroup.com/"&gt;Nielsen Norman&lt;/a&gt; research.&lt;/p&gt;
&lt;h3 id="language-correctness"&gt;Language correctness&lt;/h3&gt;&lt;p&gt;Spelling and grammatical correctness are low hanging fruit. They are
easy to achieve. Use full sentences, use punctuation, and capitalize
appropriately. But don't be a grammar stickler unreasonably; language
is flexible and always changing. Don't allow anyone the opportunity to
take your work less seriously by screwing up the basics.&lt;/p&gt;
&lt;h3 id="structuring-sentences-and-paragraphs"&gt;Structuring sentences and paragraphs&lt;/h3&gt;&lt;p&gt;Keep your sentences short. And avoid run on sentences; they are always
difficult to parse. If you use more than two commas in a sentences
(aside from in lists), the sentence is terrible. Split it up. Commas
are often used superfluously. Don't do that.&lt;/p&gt;
&lt;p&gt;Remember that if a comma separates two sentences, you can separate
them into two sentences with a period instead. And if you ever have a
list containing another list, separate the outer list with semi colons
instead of commas to provide better differentiation.&lt;/p&gt;
&lt;p&gt;Keep your paragraphs short too. In primary school you may have learned
to use 5-8 sentences per paragraph. Don't do so needlessly. 3-5
sentences can be perfectly appropriate. As both sentences and
paragraphs get longer, they appear more intimidating and can
discourage readers from continuing.&lt;/p&gt;
&lt;div class="note"&gt;
  &lt;header class="note-header"&gt;Visually speaking&lt;/header&gt;
  &lt;p&gt;
    Make your line height
    &lt;a href="https://practicaltypography.com/line-spacing.html"&gt;120-145%&lt;/a&gt;
    the height of the font. Increase the spacing between lines in a
    paragraph to make the paragraph less dense and more friendly.
  &lt;/p&gt;
  &lt;p&gt;
    Keep contrast high. Don't put very gray (or colored) text on a
    white background.
  &lt;/p&gt;
  &lt;p&gt;
    Additionally, a number of studies suggest that limiting the width
    of text increases readability. For best results, limit the width
    such
    that &lt;a href="https://baymard.com/blog/line-length-readability"&gt;50-75
    characters&lt;/a&gt; appear per line of text.
  &lt;/p&gt;
&lt;/div&gt;&lt;h4 id="don't-put-checklists-in-paragraphs"&gt;Don't put checklists in paragraphs&lt;/h4&gt;&lt;p&gt;If a document describes concrete steps that should be followed exactly
and can be reasonably summarized, don't hide the steps within
paragraphs of text. Instead use an ordered or unordered list to
clearly enumerate the expectations. &lt;strong&gt;You can't expect a checklist to
be followed when it is hidden within the sentences of a paragraph.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="structuring-sections"&gt;Structuring sections&lt;/h3&gt;&lt;p&gt;Any document (regardless the type) longer than 3-5 paragraphs should
be broken into sub-sections with summarizing headers to aid
scanning. Use the HTML &lt;code&gt;id&lt;/code&gt; attribute to allow a direct link to a
particular section in a long page. If the page has more than two
sections or vertically flows beyond a single screen, consider adding a
table of contents at the top of the page to allow the reader to find
the exact section she needs.&lt;/p&gt;
&lt;div class="note"&gt;
  &lt;header class="note-header"&gt;Visually speaking&lt;/header&gt;
  &lt;p&gt;
    Don't put large headers immediately next to each other. It is
    disruptive to have multiple lines of large text.
  &lt;/p&gt;
  &lt;p&gt;
    I almost completely avoid Github Markdown's h1/# tag because it is
    just too large and jarring relative to the rest of the text. It is
    often best for the flow of a Github Markdown document to stick to
    only h3-h4/###-#### tags for headers, using the h2/## tag for the
    document title.
  &lt;/p&gt;
&lt;/div&gt;&lt;h3 id="in-summary"&gt;In summary&lt;/h3&gt;&lt;p&gt;The aesthetic flow of a document can help or hurt the experience of a
reader consuming it. Good aesthetic "sense" in this regard can be
boiled down to a few methods that primarily revolve around simplifying
structure and facilitating the rewarding feeling of progress as a
reader reads.&lt;/p&gt;
&lt;p&gt;Writing is difficult and takes time to evolve helpfully. The dividends
are paid when process is better followed and questions are readily
clarified in writing without further human intervention. It is
incumbent on those writing and maintaining to organize effectively and
see confusion of the reader as fault of the document, not fault of the
reader. It is easier to change something yourself than to expect
others to change to accommodate you.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Fri, 18 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/writing-to-be-read.html</guid></item><item><title>Set up a Self Signed Certificate on macOS's Built in Apache</title><link>https://donatstudios.com/Self-Signed-Certificate-On-macOS-Apache</link><description>&lt;p&gt;&lt;strong&gt;Update 2019-01-29:&lt;/strong&gt; A much simpler method using a tool called &lt;code&gt;mkcert&lt;/code&gt; has come along and I have an &lt;a href="https://donatstudios.com/Local-Certificate-On-macOS-Apache"&gt;updated walkthrough&lt;/a&gt; you may want to use instead. I would recommend the &lt;code&gt;mkcert&lt;/code&gt; method unless you have a reason you explicitly need a self signed certificate.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;I recently purchased a &lt;code&gt;.app&lt;/code&gt; domain for a side project; &lt;code&gt;.app&lt;/code&gt; domains are interesting as they &lt;strong&gt;require&lt;/strong&gt; SSL at &lt;em&gt;all times&lt;/em&gt;. &lt;/p&gt;
&lt;p&gt;I like to set up my dev environments as subdomains of my actual domain, such as &lt;code&gt;local.donatstudios.com&lt;/code&gt;. It makes working with CORS and cookies a lot simpler for applications with APIs on subdomains.&lt;/p&gt;
&lt;p&gt;Doing this with &lt;code&gt;.app&lt;/code&gt; however means having to get SSL working. I found a number of tutorials of varying quality online, but none of them did the full process from start to finish, particularly solving problems with Chrome 58.&lt;/p&gt;
&lt;p&gt;This tutorial assumes you are using the built in version of Apache that comes with macOS, however you should be able to adjust paths for &lt;code&gt;brew&lt;/code&gt; or otherwise installed versions.&lt;/p&gt;
&lt;h2&gt;Creating the Certificates&lt;/h2&gt;
&lt;p&gt;First off we'll make place to do our work. We need to do this outside of sudo requiring areas due to some bugs with the Apple version of openssl.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ mkdir /tmp/crt &amp;amp;&amp;amp; cd /tmp/crt&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next we will generate your key and certificate. Replace all four &lt;code&gt;local.example.com&lt;/code&gt; entries with your full intended development subdomain. &lt;/p&gt;
&lt;p&gt;The &lt;code&gt;subjectAltName=DNS&lt;/code&gt; piece of this is required to get Chrome versions greater than 58 working.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ openssl req -newkey rsa:2048 -x509 -nodes \
    -keyout local.example.com.key \
    -new \
    -out local.example.com.crt \
    -subj /CN=local.example.com \
    -reqexts SAN \
    -extensions SAN \
    -config &amp;lt;(cat /System/Library/OpenSSL/openssl.cnf \
        &amp;lt;(printf '[SAN]\nsubjectAltName=DNS:local.example.com')) \
    -sha256 \
    -days 3650&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Apache requires a &lt;code&gt;nopass&lt;/code&gt; key, so to generate this we do the following, again adjusting paths as nessessary:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ sudo openssl rsa -in local.example.com.key -out local.example.com.nopass.key&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now that we have completed the key generation, we can move our certificates into the apache &lt;code&gt;/etc&lt;/code&gt; directory:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ sudo mkdir /etc/apache2/ssl
$ sudo mv *.key *.crt /etc/apache2/ssl&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="apache-configuration"&gt;Apache Configuration&lt;/h2&gt;
&lt;p&gt;In your favorite editor open &lt;code&gt;/etc/apache2/httpd.conf&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Uncomment the following lines (line numbers may vary):&lt;/p&gt;
&lt;p&gt;Near line 89:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LoadModule socache_shmcb_module libexec/apache2/mod_socache_shmcb.so&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Near line 144:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;LoadModule ssl_module libexec/apache2/mod_ssl.so&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Near line 528:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Include /private/etc/apache2/extra/httpd-ssl.conf&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Next open &lt;code&gt;/etc/apache2/extra/httpd-ssl.conf&lt;/code&gt;, find &lt;code&gt;&amp;lt;VirtualHost _default_:443&amp;gt;&lt;/code&gt; around line 121.&lt;/p&gt;
&lt;p&gt;Either &lt;strong&gt;comment out&lt;/strong&gt; using a &lt;code&gt;#&lt;/code&gt; at the start of each line, or &lt;strong&gt;delete&lt;/strong&gt; &lt;em&gt;every single line&lt;/em&gt; between the opening &lt;code&gt;&amp;lt;VirtualHost _default_:443&amp;gt;&lt;/code&gt; and the closing &lt;code&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/code&gt; around line 290.&lt;/p&gt;
&lt;p&gt;Presuming your sites VirtualHost is in &lt;code&gt;/etc/apache2/extra/httpd-vhosts.conf&lt;/code&gt; either change &lt;code&gt;&amp;lt;VirtualHost *:80&amp;gt;&lt;/code&gt; to &lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;&lt;/code&gt;, or duplicate your VirtualHost entry using &lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;&lt;/code&gt; if you'd like your VirtualHost accessible with and without SSL.&lt;/p&gt;
&lt;p&gt;Next, inside your sites &lt;code&gt;&amp;lt;VirtualHost *:443&amp;gt;&lt;/code&gt; block, append the following, adjusting the filenames accordingly.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  SSLEngine on
  SSLCertificateFile "/private/etc/apache2/ssl/local.example.com.crt"
  SSLCertificateKeyFile "/private/etc/apache2/ssl/local.example.com.nopass.key"&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Chrome / Safari Configuration&lt;/h2&gt;
&lt;p&gt;Next we will open your Apache ssl directory and the &amp;quot;Keychain Access&amp;quot; application:&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-console"&gt;$ open /etc/apache2/ssl
$ open /Applications/Utilities/Keychain\ Access.app&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In the Keychain Access application, select the &lt;code&gt;login&lt;/code&gt; &lt;em&gt;Keychain&lt;/em&gt; and the &lt;code&gt;Certificates&lt;/code&gt; &lt;em&gt;Category&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Then from the open Finder window, drag and drop your &lt;code&gt;.crt&lt;/code&gt; file.&lt;/p&gt;
&lt;img alt="Keychain Access" src="https://donatstudios.com/assets/65/keychain.png" /&gt;
&lt;p&gt;Double click, and change the settings for the selected certificate to &lt;strong&gt;&amp;quot;Always Trust&amp;quot;&lt;/strong&gt;.&lt;/p&gt;
&lt;img alt="Keychain Access: Trust Level" src="https://donatstudios.com/assets/65/keychain_trust.png" /&gt;
&lt;p&gt;Lastly, repeat the process of dragging and giving access in the &lt;code&gt;System&lt;/code&gt; &lt;em&gt;Keychain&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You may need to reboot, but your certificate should now work in Chrome and Safari on your local machine.&lt;/p&gt;</description><author>Donat Studios</author><pubDate>Wed, 16 May 2018 05:42:51 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/Self-Signed-Certificate-On-macOS-Apache</guid></item><item><title>New Beginnings</title><link>http://blog.pythonaro.com/2018/05/new-beginnings.html</link><description>So, after 7 intense years at Infratects (now Inlumi), it's time for me to move on.&lt;br /&gt;
&lt;br /&gt;
I have a few ideas about what to do next, but nothing set in stone yet. &lt;a href="https://www.linkedin.com/in/glacava/"&gt;My LinkedIn profile&lt;/a&gt; could do with more details, but it's a decent primer for what I do for a living - Hyperion/EPM, Python, Java, Weblogic and thereabout.&lt;br /&gt;
&lt;br /&gt;
I was a web developer in a previous life, so I enjoy hacking and automating everything, getting dirty with infrastructure and the cloud; and in 13 years working on Hyperion products, I've absorbed a pretty good amount of knowledge related to financial processes (consolidation rules, metadata, cube performance and so on) as well as a deep understanding of the innards of the EPM suite. I can tweak your database, hack your Weblogic, integrate your cloud-based authentication, script your exports and migrations, and so on; and if there is something the tools won't do... I'll build you a new tool! That's where I make the difference: at the intersection of technology and Finance, boosting the productivity of accountants. &lt;br /&gt;
&lt;br /&gt;
If this sounds interesting, ping me on &lt;a href="https://www.linkedin.com/in/glacava/"&gt;LinkedIn&lt;/a&gt; and we can have a chat.</description><author>Subclassed</author><pubDate>Wed, 16 May 2018 00:59:15 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/05/new-beginnings.html</guid></item><item><title>Filtered aggregates lands in Django 2.0!</title><link>https://tomforb.es/blog/filtered-aggregates-landed-in-django/</link><description>Big Django projects often suffer from a few problems regarding database modelling and relations. Django provides incredibly easy to use tools to model your domain along with an awesomely powerful ORM to query on them. Often back office reporting software written in Django makes extensive use of the ...</description><author>Tom Forbes</author><pubDate>Sat, 12 May 2018 17:00:39 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/filtered-aggregates-landed-in-django/</guid></item><item><title>Random Numbers</title><link>https://rjp.is/blogging/posts/random_numbers/</link><description>In which we check whether an RNG is complete.</description><author>infrequent oscillations</author><pubDate>Fri, 11 May 2018 13:03:18 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/random_numbers/</guid></item><item><title>How to start a Go project in 2018</title><link>https://boyter.org/posts/how-to-start-go-project-2018/</link><description>&lt;p&gt;This post is fairly old. See the updated version &lt;a href="https://boyter.org/posts/how-to-start-go-project-2023/"&gt;Starting a Go project in 2023&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Getting started with a Go project in 2018 is frankly a little more painful then getting anything else started IMHO. With that here is what I have been doing to get started.&lt;/p&gt;
&lt;p&gt;The first thing to do is download and install Go. I would suggest always installing from the Go website itself &lt;a href="https://golang.org/"&gt;https://golang.org/&lt;/a&gt; and following the instructions for your OS of choice.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 10 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/how-to-start-go-project-2018/</guid></item><item><title>Writing a simple JSON parser</title><link>http://notes.eatonphil.com/writing-a-simple-json-parser.html</link><description>&lt;p&gt;Writing a JSON parser is one of the easiest ways to get familiar with
parsing techniques. The format is extremely simple. It's defined
recursively so you get a slight challenge compared to, say, parsing
&lt;a href="https://en.wikipedia.org/wiki/Brainfuck"&gt;Brainfuck&lt;/a&gt;; and you probably
already use JSON. Aside from that last point, parsing
&lt;a href="https://en.wikipedia.org/wiki/S-expression"&gt;S-expressions&lt;/a&gt; for Scheme
might be an even simpler task.&lt;/p&gt;
&lt;p&gt;If you'd just like to see the code for the library, &lt;code&gt;pj&lt;/code&gt;, &lt;a href="https://github.com/eatonphil/pj"&gt;check it out
on Github&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="what-parsing-is-and-(typically)-is-not"&gt;What parsing is and (typically) is not&lt;/h3&gt;&lt;p&gt;Parsing is often broken up into two stages: lexical analysis and
syntactic analysis. Lexical analysis breaks source input into the
simplest decomposable elements of a language called "tokens".
Syntactic analysis (often itself called "parsing") receives the list
of tokens and tries to find patterns in them to meet the language
being parsed.&lt;/p&gt;
&lt;p&gt;Parsing does not determine semantic viability of an input
source. Semantic viability of an input source might include whether or
not a variable is defined before being used, whether a function is
called with the correct arguments, or whether a variable can be
declared a second time in some scope.&lt;/p&gt;
&lt;p class="note"&gt;
  There are, of course, always variations in how people choose to
  parse and apply semantic rules, but I am assuming a "traditional"
  approach to explain the core concepts.
&lt;/p&gt;&lt;h4 id="the-json-library's-interface"&gt;The JSON library's interface&lt;/h4&gt;&lt;p&gt;Ultimately, there should be a &lt;code&gt;from_string&lt;/code&gt; method that accepts a
JSON-encoded string and returns the equivalent Python dictionary.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;assert_equal(from_string('{&amp;quot;foo&amp;quot;: 1}'),
             {&amp;quot;foo&amp;quot;: 1})
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="lexical-analysis"&gt;Lexical analysis&lt;/h3&gt;&lt;p&gt;Lexical analysis breaks down an input string into tokens. Comments and
whitespace are often discarded during lexical analysis so you are left
with a simpler input you can search for grammatical matches during the
syntactic analysis.&lt;/p&gt;
&lt;p&gt;Assuming a simple lexical analyzer, you might iterate over all the
characters in an input string (or stream) and break them apart into
fundemental, &lt;strong&gt;non-recursively&lt;/strong&gt; defined language constructs such as
integers, strings, and boolean literals. In particular, strings
&lt;strong&gt;must&lt;/strong&gt; be part of the lexical analysis because you cannot throw away
whitespace without knowing that it is not part of a string.&lt;/p&gt;
&lt;p class="note"&gt;
  In a helpful lexer you keep track of the whitespace and comments
  you've skipped, the current line number and file you are in so that
  you can refer back to it at any stage in errors produced by analysis
  of the source. &lt;a href="https://v8project.blogspot.com/2018/03/v8-release-66.html"&gt;The
  V8 Javascript engine recently became able to do reproduce the exact
  source code of a function.&lt;/a&gt; This, at the very least, would need
  the help of a lexer to make possible.
&lt;/p&gt;&lt;h4 id="implementing-a-json-lexer"&gt;Implementing a JSON lexer&lt;/h4&gt;&lt;p&gt;The gist of the JSON lexer will be to iterate over the input source
and try to find patterns of strings, numbers, booleans, nulls, or JSON
syntax like left brackets and left braces, ultimately returning
each of these elements as a list.&lt;/p&gt;
&lt;p&gt;Here is what the lexer should return for an example input:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{&amp;quot;foo&amp;quot;: [1, 2, {&amp;quot;bar&amp;quot;: 2}]}'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'['&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bar'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;']'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is what this logic might begin to look like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;json_string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;json_string&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="c1"&gt;# TODO: lex booleans, nulls, numbers&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;JSON_WHITESPACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;JSON_SYNTAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Unexpected character: &lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The goal here is to try to match strings, numbers, booleans, and nulls
and add them to the list of tokens. If none of these match, check if
the character is whitespace and throw it away if so. Otherwise store
it as a token if it is part of JSON syntax (like left
brackets). Finally throw an exception if the character/string didn't
match any of these patterns.&lt;/p&gt;
&lt;p&gt;Let's extend the core logic here a little bit to support all the types
and add the function stubs.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex_bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;json_string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;json_string&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;json_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;json_number&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;json_bool&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex_bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;json_bool&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_bool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;json_null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;json_null&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;JSON_WHITESPACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;JSON_SYNTAX&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Unexpected character: &lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="lexing-strings"&gt;Lexing strings&lt;/h4&gt;&lt;p&gt;For the &lt;code&gt;lex_string&lt;/code&gt; function, the gist will be to check if the first
character is a quote. If it is, iterate over the input string until
you find an ending quote. If you don't find an initial quote, return
None and the original list. If you find an initial quote and an ending
quote, return the string within the quotes and the rest of the
unchecked input string.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;json_string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;JSON_QUOTE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;JSON_QUOTE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json_string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;json_string&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;

    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expected end-of-string quote'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="lexing-numbers"&gt;Lexing numbers&lt;/h4&gt;&lt;p&gt;For the &lt;code&gt;lex_number&lt;/code&gt; function, the gist will be to iterate over the
input until you find a character that cannot be part of a number.
(This is, of course, a gross simplification, but being more accurate
will be left as an exercise to the reader.) After finding a character
that cannot be part of a number, either return a float or int if the
characters you've accumulated number more than 0. Otherwise return
None and the original string input.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex_number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;json_number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;

    &lt;span class="n"&gt;number_characters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'-'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'e'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;number_characters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;json_number&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="n"&gt;rest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_number&lt;/span&gt;&lt;span class="p"&gt;):]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s1"&gt;'.'&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;json_number&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_number&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_number&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="lexing-booleans-and-nulls"&gt;Lexing booleans and nulls&lt;/h4&gt;&lt;p&gt;Finding boolean and null values is a very simple string match.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex_bool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;string_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;string_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;TRUE_LEN&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; \
       &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;TRUE_LEN&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'true'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;TRUE_LEN&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;string_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;FALSE_LEN&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; \
         &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;FALSE_LEN&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'false'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;FALSE_LEN&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lex_null&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;string_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;string_len&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;NULL_LEN&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; \
       &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[:&lt;/span&gt;&lt;span class="n"&gt;NULL_LEN&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'null'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;NULL_LEN&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now the lexer code is done! See the
&lt;a href="https://github.com/eatonphil/pj/blob/master/pj/lexer.py"&gt;pj/lexer.py&lt;/a&gt;
for the code as a whole.&lt;/p&gt;
&lt;h3 id="syntactic-analysis"&gt;Syntactic analysis&lt;/h3&gt;&lt;p&gt;The syntax analyzer's (basic) job is to iterate over a one-dimensional
list of tokens and match groups of tokens up to pieces of the language
according to the definition of the language. If, at any point during
syntactic analysis, the parser cannot match the current set of tokens up
to a valid grammar of the language, the parser will fail and possibly
give you useful information as to what you gave, where, and what it
expected from you.&lt;/p&gt;
&lt;h4 id="implementing-a-json-parser"&gt;Implementing a JSON parser&lt;/h4&gt;&lt;p&gt;The gist of the JSON parser will be to iterate over the tokens
received after a call to &lt;code&gt;lex&lt;/code&gt; and try to match the tokens to objects,
lists, or plain values.&lt;/p&gt;
&lt;p&gt;Here is what the parser should return for an example input:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{&amp;quot;foo&amp;quot;: [1, 2, {&amp;quot;bar&amp;quot;: 2}]}'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
             &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'['&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'{'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bar'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;':'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;']'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'}'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;assert_equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
             &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;'bar'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;}]})&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here is what this logic might begin to look like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;JSON_LEFTBRACKET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parse_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;JSON_LEFTBRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parse_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;A key structural difference between this lexer and parser is that the
lexer returns a one-dimensional array of tokens. Parsers are often
defined recursively and returns a recursive, tree-like object. Since
JSON is a data serialization format instead of a language, the parser
should produce objects in Python rather than a syntax tree on which
you could perform more analysis (or code generation in the case of a
compiler).&lt;/p&gt;
&lt;p&gt;And, again, the benefit of having the lexical analysis happen
independent from the parser is that both pieces of code are simpler
and concerned with only specific elements.&lt;/p&gt;
&lt;h4 id="parsing-arrays"&gt;Parsing arrays&lt;/h4&gt;&lt;p&gt;Parsing arrays is a matter of parsing array members and expecting a
comma token between them or a right bracket indicating the end
of the array.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;json_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;JSON_RIGHTBRACKET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json_array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;json_array&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;JSON_RIGHTBRACKET&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json_array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;JSON_COMMA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expected comma after object in array'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expected end-of-array bracket'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="parsing-objects"&gt;Parsing objects&lt;/h4&gt;&lt;p&gt;Parsing objects is a matter of parsing a key-value pair internally
separated by a colon and externally separated by a comma until you
reach the end of the object.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_object&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;json_object&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;JSON_RIGHTBRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;json_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expected string key, got: &lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json_key&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;JSON_COLON&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expected colon after key in object, got: &lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="n"&gt;json_value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:])&lt;/span&gt;

        &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;json_key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json_value&lt;/span&gt;

        &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;JSON_RIGHTBRACE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json_object&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;
        &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;JSON_COMMA&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expected comma after pair in object, got: &lt;/span&gt;&lt;span class="si"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:]&lt;/span&gt;

    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Expected end-of-object brace'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And now the parser code is done! See the
&lt;a href="https://github.com/eatonphil/pj/blob/master/pj/parser.py"&gt;pj/parser.py&lt;/a&gt;
for the code as a whole.&lt;/p&gt;
&lt;h3 id="unifying-the-library"&gt;Unifying the library&lt;/h3&gt;&lt;p&gt;To provide the ideal interface, create the &lt;code&gt;from_string&lt;/code&gt; function
wrapping the &lt;code&gt;lex&lt;/code&gt; and &lt;code&gt;parse&lt;/code&gt; functions.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;from_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And the library is complete! (ish). Check out the &lt;a href="https://github.com/eatonphil/pj"&gt;project on
Github&lt;/a&gt; for the full implementation
including basic testing setup.&lt;/p&gt;
&lt;h3 id="appendix-a:-single-step-parsing"&gt;Appendix A: Single-step parsing&lt;/h3&gt;&lt;p&gt;Some parsers choose to implement lexical and syntactic analysis in one
stage. For some languages this can simplify the parsing stage
entirely. Or, in more powerful languages like Common Lisp, it can
allow you to dynamically extend the lexer and parser in one step with
&lt;a href="https://gist.github.com/chaitanyagupta/9324402"&gt;reader macros&lt;/a&gt;.&lt;/p&gt;
&lt;p class="note"&gt;
  I wrote this library in Python to make it more accessible to
  a larger audience. However, many of the techniques used are more
  amenable to languages with pattern matching and support for monadic
  operations -- like Standard ML. If you are curious what this same
  code would look like in Standard ML, check out the &lt;a href="https://github.com/eatonphil/ponyo/blob/master/src/Encoding/Json.sml"&gt;JSON
  code in Ponyo&lt;/a&gt;.
&lt;/p&gt;&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;I wrote a short post (and a corresponding Python library) explaining lexing and parsing with JSON &lt;a href="https://t.co/3yEZlcU6i5"&gt;https://t.co/3yEZlcU6i5&lt;/a&gt; &lt;a href="https://t.co/FbksvUO9aT"&gt;https://t.co/FbksvUO9aT&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/json?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#json&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/python?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#python&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/993251098931712005?ref_src=twsrc%5Etfw"&gt;May 6, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sun, 06 May 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/writing-a-simple-json-parser.html</guid></item><item><title>Musical Update</title><link>https://rjp.is/blogging/posts/musical_update/</link><description>In which we watch/listen to eight YouTube videos of songs I quite like.</description><author>infrequent oscillations</author><pubDate>Thu, 03 May 2018 14:02:34 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/musical_update/</guid></item><item><title>Finishing up a FreeBSD experiment</title><link>http://notes.eatonphil.com/finishing-up-a-freebsd-experiment.html</link><description>&lt;p&gt;I've been using FreeBSD as my daily driver at work since
December. I've successfully done my job and I've learned a hell of a
lot forcing myself on CURRENT... But there's been a number of issues
with it that have made it difficult to keep using, so I replaced it
with Arch Linux yesterday and I no longer have those issues. This is
not the first time I've forced myself to run FreeBSD and it won't be
the last.&lt;/p&gt;
&lt;h3 id="the-freebsd-setup"&gt;The FreeBSD setup&lt;/h3&gt;&lt;p&gt;I have a Dell Developer Edition. It employs full-disk encryption with
ZFS. Not being a "disk-jockey" I cannot comment on how exhilarating an
experience running ZFS is. It didn't cause me any trouble.&lt;/p&gt;
&lt;p&gt;It has an Intel graphics card and the display server is X. I use the
&lt;a href="https://stumpwm.github.io"&gt;StumpWM&lt;/a&gt; window manager and
the &lt;a href="https://github.com/iwamatsu/slim"&gt;SLiM&lt;/a&gt; login
manager. &lt;a href="https://www.jwz.org/xscreensaver/"&gt;xscreensaver&lt;/a&gt; handles
locking the screen, &lt;a href="https://feh.finalrewind.org/"&gt;feh&lt;/a&gt; gives me
background images, &lt;a href="https://github.com/dreamer/scrot"&gt;scrot&lt;/a&gt; gives me
screenshots, and
&lt;a href="http://recordmydesktop.sourceforge.net/about.php"&gt;recordMyDesktop&lt;/a&gt;
gives me video screen capture. This list should feel familiar to users
of Arch Linux or other X-supported, bring-your-own-software operating
systems/Linux distributions.&lt;/p&gt;
&lt;h4 id="software-development"&gt;Software development&lt;/h4&gt;&lt;p&gt;I primarily work on a web application with Node/PostgreSQL and React/SASS.
I do all of this development locally on FreeBSD. I run other components of
our system in a Vagrant-managed VirtualBox virtual machine.&lt;/p&gt;
&lt;h4 id="upgrading-the-system"&gt;Upgrading the system&lt;/h4&gt;&lt;p&gt;Since I'm running CURRENT, I fetch the latest commit on Subversion and
rebuild the FreeBSD system (kernel + user-land) each weekend to get
the new hotness. This takes somewhere between 1-4 hours. I start the
process Sunday morning and come back to it after lunch. After the
system is compiled and installed, I update all the packages through
the package manager and deal with fallout from incompatible kernel
modules that send me in a crash/reboot loop on boot.&lt;/p&gt;
&lt;p&gt;This is actually the part about running FreeBSD (CURRENT) I love the
most. I've gotten more familiar with the development and distribution
of kernel modules like the WiFi, Graphics, and VirtualBox
drivers. I've learned a lot about the organization of the FreeBSD
source code. And I've gotten some improvements
&lt;a href="https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=226015"&gt;merged&lt;/a&gt;
into the FreeBSD Handbook on how to debug a core dump.&lt;/p&gt;
&lt;h3 id="issues-with-freebsd-on-my-hardware"&gt;Issues with FreeBSD on my hardware&lt;/h3&gt;&lt;p&gt;I installed CURRENT in December to get support for new Intel graphics
drivers (which have since been backported to STABLE). The built-in
Intel WiFi card is also new enough that it hadn't been backported to
STABLE. My WiFi ultimately never got more than 2-4Mbps down on the
same networks my Macbook Pro would get 120-250Mbps down. I even bought
an older Realtek USB WiFi adapter and it fared no differently. My
understanding is that this is because CURRENT turns on enough debug
flags that the entire system is not really meant to be used except for
by FreeBSD developers.&lt;/p&gt;
&lt;p&gt;It would often end up taking 10-30 seconds for a &lt;code&gt;git push&lt;/code&gt; to
happen. It would take minutes to pull new Docker images, etc. This
(like everything else) does not mean you cannot do work on FreeBSD
CURRENT, it makes it really annoying.&lt;/p&gt;
&lt;h4 id="appendix-a---headphones"&gt;Appendix A - Headphones&lt;/h4&gt;&lt;p&gt;I couldn't figure out the headphone jack at all. Configuring outputs
via &lt;code&gt;sysctl&lt;/code&gt; and &lt;code&gt;device.hints&lt;/code&gt; is either really complicated or
presented in documentation really complicatedly. I posted a few times
in #freebsd on Freenode and got eager assistance but ultimately
couldn't get the headphone jack to produce anything without incredible
distortion.&lt;/p&gt;
&lt;p&gt;Of course Spotify has no FreeBSD client and I didn't want to try the
Linux compatiblity layer (which may have worked). I tried spoofing
user agents for the Spotify web app in Chrome but couldn't find one
that worked. (I still cannot get a working one on Linux either.) So
I'd end up listening to Spotify on my phone, which would have been
acceptable except for that the studio headphones I decided I needed
were immensely under-powered by my phone.&lt;/p&gt;
&lt;h4 id="appendix-b---yubikey"&gt;Appendix B - Yubikey&lt;/h4&gt;&lt;p&gt;I couldn't figure out how to give myself non-root access to my Yubikey
which I &lt;em&gt;believe&lt;/em&gt; is the reason I ultimately wasn't able to make any
use of it. Though admittedly I don't understand a whit of GPG/PGP or
Yubikey itself.&lt;/p&gt;
&lt;h4 id="appendix-c---bhyve"&gt;Appendix C - bhyve&lt;/h4&gt;&lt;p&gt;I really wanted to use
&lt;a href="https://www.freebsd.org/doc/handbook/virtualization-host-bhyve.html"&gt;bhyve&lt;/a&gt;
as the hypervisor for my CentOS virtual machines instead of
VirtualBox. So I spent 2-3 weekends trying to get it working as a
backend for Vagrant. Unfortunately the best "supported" way of doing
this is to manually mutate VirtualBox-based Vagrant boxes and that
just repeatedly didn't work for me.&lt;/p&gt;
&lt;p&gt;When I tried using bhyve directly I couldn't get networking
right. Presumably this is because NAT doesn't work well with wireless
interfaces... And I hadn't put in enough weekends to understand
setting up proxy rules correctly.&lt;/p&gt;
&lt;h4 id="appendix-d---synaptics"&gt;Appendix D - Synaptics&lt;/h4&gt;&lt;p&gt;It is my understanding that FreeBSD has its own custom Synaptics
drivers and configuration interfaces. Whether that is the case or not,
the documentation is a nightmare and while I would have loved to punt
to a graphical interface to prevent from fat-palming the touchpad
every 30 seconds, none of the graphical configuration tools seemed to
work.&lt;/p&gt;
&lt;p&gt;A few weeks ago I think I finally got the synaptics support &lt;em&gt;on&lt;/em&gt; but I
couldn't scroll or select text anymore. I also had to disable
synaptics, restart X, enable synaptics, and restart X on each boot for
it to successfully register the mouse. I meant to post in #freebsd on
Freenode where I probably would have found a solution but :shrugs:.&lt;/p&gt;
&lt;h4 id="appendix-e---sleep"&gt;Appendix E - Sleep&lt;/h4&gt;&lt;p&gt;Well sleep doesn't really work on any modern operating system.&lt;/p&gt;
&lt;h3 id="freebsd-is-awesome"&gt;FreeBSD is awesome&lt;/h3&gt;&lt;p&gt;I enjoy picking on my setup, but it should be impressive that you can
do real-world work on FreeBSD. If I had a 3-4 year old laptop instead
of a 1-2 year old laptop, most of my issues would be solved.&lt;/p&gt;
&lt;p&gt;Here are some reasons to like FreeBSD.&lt;/p&gt;
&lt;h4 id="less-competition"&gt;Less competition&lt;/h4&gt;&lt;p&gt;This is kind of stupid. But it's easier to find work to do (e.g. docs
to fix, bugs to report, ports to add/update, drivers to test) on
FreeBSD. I'm really disappointed to be back on Linux because I like
being closer to the community and knowing there are ways I can
contribute and learn. It's difficult to find the right combination of
fending/learning for yourself and achieving a certain level of
productivity.&lt;/p&gt;
&lt;h4 id="package-management-(culture)"&gt;Package management (culture)&lt;/h4&gt;&lt;p&gt;Rolling packages are really important to me as a developer. When I've
run Ubuntu and Debian desktops in the past, I typically built 5-15
major (to my workflow) components from source myself. This is
annoying. Rolling package systems are both easier to use and easier to
contribute to... The latter point may be a coincidence.&lt;/p&gt;
&lt;p&gt;In FreeBSD, packages are rolling and the base system (kernel +
userland) is released every year or two if you run the
recommended/supported "flavors" of FreeBSD (i.e. not CURRENT). If
you're running CURRENT then everything is rolling.&lt;/p&gt;
&lt;p&gt;Packages are binary, but you can build them from source if needed.&lt;/p&gt;
&lt;h4 id="source"&gt;Source&lt;/h4&gt;&lt;p&gt;FreeBSD has an older code base than Linux does but still manages to be
much better organized. OpenBSD and Minix are even better organized but
I don't consider them in the grouping as mainstream general-purpose
operating systems like FreeBSD and Linux. Linux is an awful mess
and is very intimidating, though I hope to get over that.&lt;/p&gt;
&lt;h4 id="old-school-interfaces"&gt;Old-school interfaces&lt;/h4&gt;&lt;p&gt;There's no systemd so starting X is as simple as &lt;code&gt;startx&lt;/code&gt; (but you can
enable the login manager service to have it launch on boot). You
configure your network interfaces via &lt;code&gt;ifconfig&lt;/code&gt;, &lt;code&gt;wpa_supplicant&lt;/code&gt;,
and &lt;code&gt;dhclient&lt;/code&gt;.&lt;/p&gt;
&lt;h4 id="alternatives"&gt;Alternatives&lt;/h4&gt;&lt;p&gt;&lt;a href="https://www.trueos.org/"&gt;PCBSD or TrueOS&lt;/a&gt; may be a good option for
desktop users but something about the project turns me off (maybe it's
the scroll-jacking website).&lt;/p&gt;
&lt;h3 id="picking-arch-linux"&gt;Picking Arch Linux&lt;/h3&gt;&lt;p&gt;In any case, I decided it was time to stop waiting for &lt;code&gt;git push&lt;/code&gt; to
finish. I had run Gentoo at work for 3-4 months before I installed
FreeBSD. But I still had nightmares of resolving dependencies during
upgrades. I needed a binary package manager (not hard to find) and a
rolling release system.&lt;/p&gt;
&lt;h4 id="installing-arch-stinks"&gt;Installing Arch stinks&lt;/h4&gt;&lt;p&gt;Many of my old coworkers at Linode run Arch Linux at home so I've
looked into it a few times. It absolutely meets my rolling release and
binary packaging needs. But I've been through the installation once
before (and I've been through Gentoo's) and loathed the minutes-long
effort required to set up full-disk encryption. Also, systemd? :(&lt;/p&gt;
&lt;h4 id="how-about-void-linux?"&gt;How about Void Linux?&lt;/h4&gt;&lt;p&gt;Void Linux looked promising and avoids systemd (which legitimately
adds complexity and new tools to learn for desktop users with graphics
and WiFi/DHCP networking). It has a rolling release system and binary
packages, but overall didn't seem popular enough. I worried I'd be in
the same boat as in Debian/Ubuntu building lots of packages myself.&lt;/p&gt;
&lt;h4 id="what-about-arch-based-distros?"&gt;What about Arch-based distros?&lt;/h4&gt;&lt;p&gt;Eventually I realized &lt;a href="http://antergos.com/"&gt;Antergos&lt;/a&gt; and
&lt;a href="https://manjaro.org/"&gt;Manjaro&lt;/a&gt; are two (Distrowatch-rated) popular
distributions that are based on Arch and would provide me with the
installer I really wanted. I read more about Manjaro and found it was
pretty divergent from Arch. That didn't sound appealing. Divergent
distributions like Manjaro and Mint exist to cause trouble. Antergos,
on the other hand, seemed to be a thin layer around Arch including a
graphical installer and its own few package repositories. It seemed
easy enough to remove after the installation was finished.&lt;/p&gt;
&lt;h3 id="antergos-linux"&gt;Antergos Linux&lt;/h3&gt;&lt;p&gt;I ran the Antergos installer and the first time around, my touchpad
didn't work at all. I tried a USB mouse (that to be honest, may have
been broken anyway) but it didn't seem to be recognized. I rebooted
and my touchpad worked.&lt;/p&gt;
&lt;p&gt;I tried to configure WiFi using the graphical NetworkManager provided
but it was super buggy. Menus kept expanding and contracting as I
moused over items. And it ultimately never prompted me for a password
to the locked networks around me. (It showed lock icons beside the
locked networks.)&lt;/p&gt;
&lt;p&gt;I spent half an hour trying to configure the WiFi manually. After I
got it working (and "learned" all the fun new modern tools like &lt;code&gt;ip&lt;/code&gt;,
&lt;code&gt;iw&lt;/code&gt;, &lt;code&gt;dhcpcd&lt;/code&gt;, &lt;code&gt;iwconfig&lt;/code&gt;, and systemd networking), the Antergos
installer would crash at the last step for some error related to not
being able to update itself.&lt;/p&gt;
&lt;p&gt;At this point I gave up. The Antergos installer was half-baked, buggy,
and was getting me nowhere.&lt;/p&gt;
&lt;h3 id="anarchy-linux"&gt;Anarchy Linux&lt;/h3&gt;&lt;p&gt;Still loathe to spend a few minutes configuring disk encryption
manually, I interneted until I found &lt;a href="https://anarchy-linux.org/"&gt;Anarchy
Linux&lt;/a&gt; (which used to be Arch Anywhere).&lt;/p&gt;
&lt;p&gt;This installer seemed even more promising. It is a TUI installer so no
need for a mouse and there are more desktop environments to pick from
(including i3 and Sway) or avoid.&lt;/p&gt;
&lt;p&gt;It was a little concerning that Anarchy Linux also intends to be its
own divergent Arch-based distribution, but in the meantime it still
offers support for installing vanilla Arch.&lt;/p&gt;
&lt;p&gt;It worked.&lt;/p&gt;
&lt;h3 id="life-on-arch"&gt;Life on Arch&lt;/h3&gt;&lt;p&gt;I copied over all my configs from my FreeBSD setup and they all
worked. That's pretty nice (also speaks to the general compatibility
of software between Linux and FreeBSD). StumpWM, SLiM, scrot,
xscreensaver, feh, Emacs, Tmux, ssh, kubectl, font settings,
keyboarding bindings, etc.&lt;/p&gt;
&lt;p&gt;Getting Powerline working was a little weird. The &lt;code&gt;powerline&lt;/code&gt; and
&lt;code&gt;powerline-fonts&lt;/code&gt; packages don't seem to install patched fonts
(e.g. &lt;code&gt;Noto Sans for Powerline&lt;/code&gt;). I prefer to use these than the
alternative of specifying multiple fonts for fallbacks because I have
font settings in multiple places (e.g. .Xresources, .emacs, etc) and
the syntax varies in each config. So ultimately I cloned the
&lt;code&gt;github.com/powerline/fonts&lt;/code&gt; repo and ran the &lt;code&gt;install.sh&lt;/code&gt; script
there to get the patched fonts.&lt;/p&gt;
&lt;p&gt;But hey, there's a Spotify client! It works! And the headphone jack
just works after installing &lt;code&gt;alsa-utils&lt;/code&gt; and running &lt;code&gt;alsamixer&lt;/code&gt;. And
my WiFi speed is 120Mbps-250Mbps down on all the right networks!&lt;/p&gt;
&lt;p&gt;I can live with this.&lt;/p&gt;
&lt;h3 id="random-background"&gt;Random background&lt;/h3&gt;&lt;p&gt;Each time I join a new company, I try to use the change as an excuse
to force myself to try different workflows and learn something new
tangential to the work I actually do. I'd been a Vim and Ubuntu
desktop user since highschool. In 2015, I took a break from work on
the East Coast to live in a school bus in Silver City, New Mexico. I
swapped out my Ubuntu and Vim dev setup for FreeBSD and Emacs. I kept
GNOME 3 because I liked the asthetic. I spent 6 months with this setup
forcing myself to use it as my daily-driver doing full-stack, contract
web development gigs.&lt;/p&gt;
&lt;p&gt;In 2016, I joined Linode and took up the company Macbook Pro. I wasn't
as comfortable at the time running Linux on my Macbook, but a
determined coworker put Arch on his. I was still the only one
running Emacs (everyone else used Vim or VS Code) for Python and React
development.&lt;/p&gt;
&lt;p&gt;I joined Capsule8 in late 2017 and put Gentoo on my Dell Developer
Edition. Most people ran Ubuntu on the Dell or macOS. I'd never used
Gentoo on a desktop before but liked the systemd-optional design and
similarities to FreeBSD. I ran Gentoo for 3-4 months but was
constantly breaking it during upgrades, and the monthly, full-system
upgrades themselves took 1-2 days. I didn't have the chops or patience
to deal with it.&lt;/p&gt;
&lt;p&gt;So I used FreeBSD for 5 months and now I'm back on Linux.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sat, 28 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/finishing-up-a-freebsd-experiment.html</guid></item><item><title>Vignettes - Good Fight</title><link>https://rjp.is/blogging/posts/vignette-good-fight/</link><description>In which we excerpt some 'The Good Fight' vignettes.</description><author>infrequent oscillations</author><pubDate>Tue, 24 Apr 2018 08:07:54 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/vignette-good-fight/</guid></item><item><title>Python SimpleHTTPServer to serve a directory</title><link>https://boyter.org/posts/python-simplehttpserver/</link><description>&lt;p&gt;Something I always forget and have to search for is how to use Python to serve a directory for local testing and the like. Including it below so I have a copy I can always easily look it up.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python -m SimpleHTTPServer 8090
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and in Python 3&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;python3 -m http.server
&lt;/code&gt;&lt;/pre&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 23 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/python-simplehttpserver/</guid></item><item><title>Home Server Networking</title><link>https://captnemo.in/blog/2018/04/22/home-server-networking/</link><description>&lt;p&gt;Next in the Home Server series, this post documents how I got the networking setup to
serve content publicly from my under-the-tv server.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Colorful block diagram for the networking setup" src="/img/networking.jpg" /&gt;&lt;/p&gt;

&lt;h2 id="background"&gt;Background&lt;/h2&gt;

&lt;p&gt;My home server runs on a mix of Docker/Traefik orchestrated via Terraform. The source code is
at &lt;a href="https://git.captnemo.in/nemo/nebula"&gt;https://git.captnemo.in/nemo/nebula&lt;/a&gt; (self-hosted, dogfooding FTW!) if you wanna take a look.&lt;/p&gt;

&lt;p&gt;The ISP is ACT Bangalore&lt;sup id="fnref:1"&gt;&lt;a class="footnote" href="#fn:1" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;. They offer decent bandwidth and I’ve been a customer long time.&lt;/p&gt;

&lt;h2 id="public-static-ip"&gt;Public Static IP&lt;/h2&gt;

&lt;p&gt;In order to host content, you need a stable public IP. Unfortunately, ACT puts all of its customers
in Bangalore behind a NAT &lt;sup id="fnref:2"&gt;&lt;a class="footnote" href="#fn:2" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;. As a result, I decided to get a &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-use-floating-ips-on-digitalocean"&gt;Floating IP from Digital Ocean&lt;/a&gt; &lt;sup id="fnref:3"&gt;&lt;a class="footnote" href="#fn:3" rel="footnote"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The Static IP is attached to a cheap Digital Ocean Droplet (10$/mo). If you resolve &lt;code class="language-plaintext highlighter-rouge"&gt;bb8.fun&lt;/code&gt;, this is the IP you will get:&lt;/p&gt;

&lt;div class="language-plaintext highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;Name:   bb8.fun
Address: 139.59.48.222
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The droplet has a public static IP of it’s own as well: &lt;code class="language-plaintext highlighter-rouge"&gt;139.59.22.234&lt;/code&gt;. The reason I picked a Floating IP is because DO gives them for free, and I can switch between instances later without worrying about it.&lt;/p&gt;

&lt;h2 id="floating-ip"&gt;Floating IP&lt;/h2&gt;

&lt;p&gt;On the Digital Ocean infrastructure side, this IP is not directly attached to an interface on your droplet. Instead,
DO uses something called “Anchor IP”:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Network traffic between a Floating IP and a Droplet flows through an anchor IP, which is an IP address aliased to the Droplet’s public network interface (eth0). You should bind any public services that you want to make highly available through a Floating IP to the anchor IP.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, now my Droplet has 2 different IPs that I can use:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Droplet Public IP (&lt;code class="language-plaintext highlighter-rouge"&gt;139.59.22.234&lt;/code&gt;), assigned directly to the &lt;code class="language-plaintext highlighter-rouge"&gt;eth0&lt;/code&gt; interface.&lt;/li&gt;
  &lt;li&gt;Droplet Anchor IP (&lt;code class="language-plaintext highlighter-rouge"&gt;10.47.0.5&lt;/code&gt;), setup as an alias to the &lt;code class="language-plaintext highlighter-rouge"&gt;eth0&lt;/code&gt; interface.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This doubles the number of services I can listen to. I could have (for eg) - 2 different webservers
on both of these IPs.&lt;/p&gt;

&lt;h2 id="openvpn"&gt;OpenVPN&lt;/h2&gt;

&lt;p&gt;In order to establish NAT-punching connectivity between the Droplet and the Home Server, I run OpenVPN server
on the Droplet and &lt;code class="language-plaintext highlighter-rouge"&gt;openvpn-client&lt;/code&gt; on the homeserver.&lt;sup id="fnref:4"&gt;&lt;a class="footnote" href="#fn:4" rel="footnote"&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://www.digitalocean.com/community/tutorials/how-to-set-up-an-openvpn-server-on-ubuntu-16-04" title="by Justin Ellingwood"&gt;Digital Ocean Guide&lt;/a&gt; is a great resource if you ever have to do this. 2 specific IPs on the OpenVPN
network are marked as static:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Droplet: &lt;code class="language-plaintext highlighter-rouge"&gt;10.8.0.1&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Home Server: &lt;code class="language-plaintext highlighter-rouge"&gt;10.8.0.14&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="home-server---networking"&gt;Home Server - Networking&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;The server has a private static IP assigned to its &lt;code class="language-plaintext highlighter-rouge"&gt;eth0&lt;/code&gt; interface&lt;/li&gt;
  &lt;li&gt;It also has a private static IP assiged to its &lt;code class="language-plaintext highlighter-rouge"&gt;tun0&lt;/code&gt; interface&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are primarily 3 kinds of services that I like to run:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Accessible only from within the home network (Timemachine backups, for eg) (Internal). This I publish on the &lt;code class="language-plaintext highlighter-rouge"&gt;eth0&lt;/code&gt; interface.&lt;/li&gt;
  &lt;li&gt;Accessible only from the public internet (Wiki) (Strictly Public). These I publish on the &lt;code class="language-plaintext highlighter-rouge"&gt;tun0&lt;/code&gt; interface and proxy via the droplet.&lt;/li&gt;
  &lt;li&gt;Accessible from both places (Emby, AirSonic) (Public). These I pubish on both &lt;code class="language-plaintext highlighter-rouge"&gt;tun0&lt;/code&gt; and the &lt;code class="language-plaintext highlighter-rouge"&gt;eth0&lt;/code&gt; interface on the homeserver.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id="docker-networking-basics"&gt;Docker Networking Basics&lt;/h2&gt;

&lt;p&gt;Docker runs its own internal network for services, and lets you “publish” these services
by forwarding traffic from a given interface to them.&lt;/p&gt;

&lt;p&gt;In plain docker-cli, this would be:&lt;/p&gt;

&lt;p&gt;&lt;code class="language-plaintext highlighter-rouge"&gt;docker run nginx --publish 443:443,80:80&lt;/code&gt; (forward traffic on 443,80 on all interfaces to the container)&lt;/p&gt;

&lt;p&gt;Since I use Terraform, it looks &lt;a href="https://git.captnemo.in/nemo/nebula/src/branch/master/docker/traefik.tf"&gt;like the following for Traefik&lt;/a&gt;:&lt;/p&gt;

&lt;div class="language-perl highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Admin Backend&lt;/span&gt;
&lt;span class="nv"&gt;ports&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;internal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1111&lt;/span&gt;
  &lt;span class="nv"&gt;external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1111&lt;/span&gt;
  &lt;span class="nv"&gt;ip&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="si"&gt;ips&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="si"&gt;eth0&lt;/span&gt;&lt;span class="err"&gt;"]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;ports&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;internal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1111&lt;/span&gt;
  &lt;span class="nv"&gt;external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1111&lt;/span&gt;
  &lt;span class="nv"&gt;ip&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="si"&gt;ips&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="si"&gt;tun0&lt;/span&gt;&lt;span class="err"&gt;"]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Local Web Server&lt;/span&gt;
&lt;span class="nv"&gt;ports&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;internal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
  &lt;span class="nv"&gt;external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
  &lt;span class="nv"&gt;ip&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="si"&gt;ips&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="si"&gt;eth0&lt;/span&gt;&lt;span class="err"&gt;"]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Local Web Server (HTTPS)&lt;/span&gt;
&lt;span class="nv"&gt;ports&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;internal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
  &lt;span class="nv"&gt;external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
  &lt;span class="nv"&gt;ip&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="si"&gt;ips&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="si"&gt;eth0&lt;/span&gt;&lt;span class="err"&gt;"]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Proxied via sydney.captnemo.in&lt;/span&gt;
&lt;span class="nv"&gt;ports&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;internal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
  &lt;span class="nv"&gt;external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;443&lt;/span&gt;
  &lt;span class="nv"&gt;ip&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="si"&gt;ips&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="si"&gt;tun0&lt;/span&gt;&lt;span class="err"&gt;"]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nv"&gt;ports&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;internal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
  &lt;span class="nv"&gt;external&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
  &lt;span class="nv"&gt;ip&lt;/span&gt;       &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;"&lt;/span&gt;&lt;span class="si"&gt;${var&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="si"&gt;ips&lt;/span&gt;&lt;span class="err"&gt;["&lt;/span&gt;&lt;span class="si"&gt;tun0&lt;/span&gt;&lt;span class="err"&gt;"]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are 3 “services” exposed by Traefik on 3 ports:&lt;/p&gt;

&lt;dl&gt;
  &lt;dt&gt;Traefik Admin Interface&lt;/dt&gt;
  &lt;dd&gt;Useful for debugging. I leave this in Read-Only mode with no authentication. This is an &lt;em&gt;Internal&lt;/em&gt; service&lt;/dd&gt;
  &lt;dt&gt;HTTP, Port 80&lt;/dt&gt;
  &lt;dd&gt;This redirects users to the next entrypoint (HTTPS). This is a &lt;em&gt;Public&lt;/em&gt; service.&lt;/dd&gt;
  &lt;dt&gt;HTTPS, Port 443&lt;/dt&gt;
  &lt;dd&gt;This is where most of the traefik flows. This is a &lt;em&gt;Public&lt;/em&gt; service.&lt;/dd&gt;
&lt;/dl&gt;

&lt;p&gt;For all 3 of the above, Docker forwards traffic from both OpenVPN, as well as the home network. OpenVPN lets me access this from my laptop when I’m not at home, which is helpful for debugging issues. However, to keep the Admin Interface internal, it is not published to the internet.&lt;/p&gt;

&lt;h1 id="internet-access"&gt;Internet Access&lt;/h1&gt;

&lt;p&gt;The “bridge” between the Floating IP and the OpenVPN IP (both on the Digital Ocean droplet) is &lt;code class="language-plaintext highlighter-rouge"&gt;simpleproxy&lt;/code&gt;. It is a &lt;a href="https://github.com/vzaliva/simpleproxy"&gt;barely-maintained 200 line TCP-proxy&lt;/a&gt;. I picked it up because of its ease of use as a TCP Proxy. I specifically looked for a TCP Proxy because:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;I did not want to terminate SSL on Digital Ocean, since Traefik was already doing LetsEncrypt cert management for me&lt;/li&gt;
  &lt;li&gt;I also wanted to proxy non-web services (more below).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The simpleproxy configuration consists of a few systemd units:&lt;/p&gt;

&lt;div class="language-ini highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nn"&gt;[Service]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="py"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;simple&lt;/span&gt;
&lt;span class="py"&gt;WorkingDirectory&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/tmp&lt;/span&gt;
&lt;span class="c"&gt;# Forward Anchor IP 80 -&amp;gt; Home Server VPN 80
&lt;/span&gt;&lt;span class="py"&gt;ExecStart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;/usr/bin/simpleproxy -L 10.47.0.5:80 -R 10.8.0.14:80&lt;/span&gt;
&lt;span class="py"&gt;Restart&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;on-abort&lt;/span&gt;
&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;[Install]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="py"&gt;WantedBy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;multi-user.target&lt;/span&gt;
&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nn"&gt;[Unit]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="py"&gt;Description&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;Simple Proxy&lt;/span&gt;
&lt;span class="py"&gt;After&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;network.target&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I run 3 of these: 2 for HTTP/HTTPS, and another one for SSH.&lt;/p&gt;

&lt;p&gt;While I use simpleproxy for its stability and simplicity, you could also use iptables to
achieve the same result.&lt;/p&gt;

&lt;h1 id="ssh-tunelling"&gt;SSH Tunelling&lt;/h1&gt;

&lt;p&gt;When I’m on the go, there are 3 different SSH services I might need:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Digital Ocean Droplet&lt;/li&gt;
  &lt;li&gt;Home Server&lt;/li&gt;
  &lt;li&gt;Git (&lt;code class="language-plaintext highlighter-rouge"&gt;gitea&lt;/code&gt; runs its own internal git server)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;My initial plan was:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Forward Port 22 Floating IP Traffic to Gitea.&lt;/li&gt;
  &lt;li&gt;Use the &lt;code class="language-plaintext highlighter-rouge"&gt;eth0&lt;/code&gt; interface on the droplet to run the droplet &lt;code class="language-plaintext highlighter-rouge"&gt;sshd&lt;/code&gt; service.&lt;/li&gt;
  &lt;li&gt;Keep the Home Server SSH forwarded to OpenVPN, so I can access it over the VPN network.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Unfortunately, that didn’t work out well, because &lt;code class="language-plaintext highlighter-rouge"&gt;sshd&lt;/code&gt; &lt;a href="https://serverfault.com/questions/605446/make-sshd-listen-to-a-specific-interface"&gt;doesn’t support listening on an Interface&lt;/a&gt;. I could have used the Public Droplet IP, but I didn’t like the idea.&lt;/p&gt;

&lt;p&gt;The current setup instead involves:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Running the droplet &lt;code class="language-plaintext highlighter-rouge"&gt;sshd&lt;/code&gt; on a separate port entirely (2222).&lt;/li&gt;
  &lt;li&gt;The &lt;code class="language-plaintext highlighter-rouge"&gt;simpleproxy&lt;/code&gt; service forwarding port 22 traefik to 2222 on OpenVPN IP which is then published by Docker to the &lt;code class="language-plaintext highlighter-rouge"&gt;gitea&lt;/code&gt; container’s port 22.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://git.captnemo.in/nemo/nebula/src/branch/master/docker/conf/traefik.toml"&gt;The complete traefik configuration&lt;/a&gt; is also available if you wanna look at the entrypoints in detail.&lt;/p&gt;

&lt;h1 id="caveats"&gt;Caveats&lt;/h1&gt;

&lt;h2 id="traefik-public-access"&gt;Traefik Public Access&lt;/h2&gt;

&lt;p&gt;You might have noticed that because &lt;code class="language-plaintext highlighter-rouge"&gt;traefik&lt;/code&gt; is listening on both &lt;code class="language-plaintext highlighter-rouge"&gt;eth0&lt;/code&gt; and &lt;code class="language-plaintext highlighter-rouge"&gt;tun0&lt;/code&gt;, there is no guarantee of a “strictly internal” service via Traefik. Traefik just uses the Host headers in the request (or SNI) to determine the container to which it needs to forward the request. I use &lt;code class="language-plaintext highlighter-rouge"&gt;*.in.bb8.fun&lt;/code&gt; for internaly accessible services, and &lt;code class="language-plaintext highlighter-rouge"&gt;*.bb8.fun&lt;/code&gt; for public. But if someone decides to spoof the headers, they can access the Internal service.&lt;/p&gt;

&lt;p&gt;Since I’m aware of the risk, I do not publish anything via traefik that I’m not comfortable putting on the internet. Only a couple of services are marked as “internal-also”, and are published on both. Services like Prometheus are not published via Traefik.&lt;/p&gt;

&lt;h2 id="2-servers"&gt;2 Servers&lt;/h2&gt;

&lt;p&gt;Running and managing 2 servers takes a bit more effort, and has more moving parts.
But I use the droplet for other tasks as well (running my &lt;a href="https://captnemo.in/dnscrypt/"&gt;DNSCrypt Server&lt;/a&gt;, for eg).&lt;/p&gt;

&lt;h2 id="original-ip-address"&gt;Original IP Address&lt;/h2&gt;

&lt;p&gt;Since SimpleProxy does not support the &lt;a href="https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt"&gt;Proxy Protocol&lt;/a&gt;,
both Traefik and Gitea/SSH servers don’t get informed about the original IP Address. I plan to fix that by switching to HAProxy TCP-mode.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;If you’re interested in my &lt;a href="/setup/homeserver/"&gt;self-hosting setup&lt;/a&gt;, I’m using Terraform + Docker, the code is hosted on &lt;a href="https://git.captnemo.in/nemo/nebula/"&gt;the same server&lt;/a&gt;, and I’ve been writing about my experience and learnings:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;a href="/blog/2017/09/17/home-server-build/"&gt;Part 1, Hardware&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/blog/2017/11/09/home-server-update/"&gt;Part 2, Terraform/Docker&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/blog/2017/12/18/home-server-learnings/"&gt;Part 3, Learnings&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/blog/2017/12/31/migrating-from-google/"&gt;Part 4, Migrating from Google (and more)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/blog/2018/04/22/home-server-networking/"&gt;Part 5, Home Server Networking&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="/blog/2019/02/24/btrfs-raid-device-replacement-story/"&gt;Part 6, btrfs RAID device replacement&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you have any comments, &lt;a href="/contact/"&gt;reach out to me&lt;/a&gt;&lt;/p&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:1"&gt;
      &lt;p&gt;If you get lucky with their customer support, some of the folks I know have a static public IP on their home setup. In my case, they asked me to upgrade to a corporate plan. &lt;a class="reversefootnote" href="#fnref:1"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:2"&gt;
      &lt;p&gt;I once scanned their entire network using &lt;code class="language-plaintext highlighter-rouge"&gt;masscan&lt;/code&gt;. It was fun: &lt;a href="https://medium.com/@captn3m0/i-scanned-all-of-act-bangalore-customers-and-the-results-arent-surprising-fecf9d7fe775"&gt;https://medium.com/@captn3m0/i-scanned-all-of-act-bangalore-customers-and-the-results-arent-surprising-fecf9d7fe775&lt;/a&gt; &lt;a class="reversefootnote" href="#fnref:2"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:3"&gt;
      &lt;p&gt;AWS calls its “permanent” IP addresses “Elastic” and Digital Ocean calls them “Floating”. We really need better names in this industry. &lt;a class="reversefootnote" href="#fnref:3"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:4"&gt;
      &lt;p&gt;Migrating to Wireguard is on my list, but I haven’t found any good documentation on running a hub-spoke network so far. &lt;a class="reversefootnote" href="#fnref:4"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</description><author>Nemo's Home</author><pubDate>Sun, 22 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/04/22/home-server-networking/</guid></item><item><title>Xonsh and Midnight Commander</title><link>https://blog.nawaz.org/posts/2018/Apr/xonsh-and-midnight-commander/</link><description>&lt;p&gt;At some point in the last year, I switched to the
&lt;a class="reference external" href="http://xon.sh/"&gt;xonsh&lt;/a&gt; shell. It is a bash-like shell written in
Python. The nice thing about it is you can write your scripts using
Python syntax. Another nice thing is you can use it in&amp;nbsp;Windows.&lt;/p&gt;
&lt;p&gt;One of the headaches with …&lt;/p&gt;</description><author>Beetle Space</author><pubDate>Sat, 21 Apr 2018 10:00:00 GMT</pubDate><guid isPermaLink="true">https://blog.nawaz.org/posts/2018/Apr/xonsh-and-midnight-commander/</guid></item><item><title>Managing a developer shell with Docker</title><link>https://bergie.iki.fi/blog/docker-developer-shell/</link><description>&lt;p&gt;When I’m not in &lt;a href="https://flowhub.io/ide/"&gt;Flowhub-land&lt;/a&gt;, I’m used to developing software in a quite customized command line based development environment. Like for many, the cornerstones of this for me are &lt;a href="https://www.vim.org"&gt;vim&lt;/a&gt; and &lt;a href="https://github.com/tmux/tmux/wiki"&gt;tmux&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As customization increases, it becomes important to have a way to manage that and distribute it across the different computers. For years, I’ve used a &lt;a href="https://github.com/bergie/dotfiles"&gt;dotfiles repository&lt;/a&gt; on GitHub together with &lt;a href="https://www.gnu.org/software/stow/"&gt;GNU Stow&lt;/a&gt; for this.&lt;/p&gt;

&lt;p&gt;However, this still means I have to install all the software and tools before I can have my environment up and running.&lt;/p&gt;

&lt;h2 id="using-docker"&gt;Using Docker&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.docker.com"&gt;Docker&lt;/a&gt; is a tool for building and running software in a containerized fashion. Recently &lt;a href="https://github.com/tiagodeoliveira"&gt;Tiago&lt;/a&gt; gave me the inspiration to use Docker not only for distributing production software, but also for actually running my development environment.&lt;/p&gt;

&lt;p&gt;Taking ideas from &lt;a href="https://github.com/tiagodeoliveira/docker-shell"&gt;his setup&lt;/a&gt;, I built upon my existing dotfiles and built a &lt;a href="https://hub.docker.com/r/bergie/shell/"&gt;reusable developer shell container&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With this, I only need Docker installed on a machine, and then I’m two commands away from having my normal development environment:&lt;/p&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker volume create workstation
&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;-v&lt;/span&gt; ~/Projects:/projects &lt;span class="nt"&gt;-v&lt;/span&gt; workstation:/root &lt;span class="nt"&gt;-v&lt;/span&gt; ~/.ssh:/keys &lt;span class="nt"&gt;--name&lt;/span&gt; workstation &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; bergie/shell
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here’s how it looks in action:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Working on NoFlo inside Docker shell" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/vim-developer-shell-docker.png" /&gt;&lt;/p&gt;

&lt;p&gt;Once I update my Docker setup (for example to install or upgrade some tool), I can get the latest version on a machine with:&lt;/p&gt;

&lt;div class="language-shell highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;docker pull bergie/shell
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At least in theory this should give me a fully identical working environment regardless of the host machine. Linux VPS, a MacBook, or a Windows machine should all be able to run this. And soon, this should also work out of the box &lt;a href="https://chromeunboxed.com/news/chromebook-containers-virtual-machine-crostini-google-io"&gt;on Chromebooks&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="setting-this-up"&gt;Setting this up&lt;/h2&gt;

&lt;p&gt;The basics are pretty simple. I already had a repository for my dotfiles, so I only needed to write &lt;a href="https://github.com/bergie/dotfiles/blob/master/Dockerfile"&gt;a Dockerfile&lt;/a&gt; to install and set up all my software.&lt;/p&gt;

&lt;p&gt;To make things even easier, I &lt;a href="https://github.com/bergie/dotfiles/blob/master/.travis.yml"&gt;configured Travis&lt;/a&gt; so that every time I push some change to the dotfiles repository, it will create and publish a new container image.&lt;/p&gt;

&lt;h2 id="further-development-ideas"&gt;Further development ideas&lt;/h2&gt;

&lt;p&gt;So far this setup seems to work pretty well. However, here are some ideas for further improvements:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;ARM build&lt;/strong&gt;: Sometimes I need to work on Raspberry Pis. It might be nice to cross-compile an ARM version of the same setup&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Key management&lt;/strong&gt;: Currently I create new SSH keys for each host machine, and then upload them to the relevant places. With this setup I could use a USB stick, or maybe even a &lt;a href="https://www.yubico.com/products/yubikey-hardware/"&gt;Yubikey&lt;/a&gt; to manage them&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Application authentication&lt;/strong&gt;: Since the Docker image is public, it doesn’t come with any secrets built in. This means I still need to authenticate with tools like NPM and Travis. It might be interesting to manage these together with my SSH keys&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;SSH host&lt;/strong&gt;: with some tweaking it might be possible to run the same container on cloud services. Then I’d need a way to get my SSH public keys there and start an SSH server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you have ideas on how to best implement the above, please &lt;a href="mailto:henri.bergius@iki.fi"&gt;get in touch&lt;/a&gt;.&lt;/p&gt;</description><author>Henri Bergius</author><pubDate>Thu, 19 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://bergie.iki.fi/blog/docker-developer-shell/</guid></item><item><title>Nespresso Blends - a comprehensive spreadsheet</title><link>http://blog.pythonaro.com/2018/04/nespresso-blends-comprehensive.html</link><description>As a faithful &lt;a href="https://www.nespresso.com/" target="_blank"&gt;Nespresso&lt;/a&gt; user, I was a bit shocked last month when I discovered one of my favourite blends contained Robusta. I had always assumed all blends were 100% Arabica and alas, that was not the case. So I started looking up what is what, but I was quickly overwhelmed - I wasn't going to browse through 24 pages of slow-loading images to read all blurbs. Enter Python.&lt;br /&gt;
&lt;br /&gt;
As it often happens, &lt;a href="https://xkcd.com/974/" target="_blank"&gt;the situation degenerated&lt;/a&gt; quickly. The result is &lt;a alt="Nespresso Blend Data Spreadsheet" href="http://static.pythonaro.com/coffee0.xlsx"&gt;an Excel spreadsheet &lt;/a&gt;(also available &lt;a href="https://docs.google.com/spreadsheets/d/e/2PACX-1vQHAG1wLaUR2d1oLt35SCu__pSFStX0MfppWD-ZLr2R-JYgbqOeYgv7EOlsoPC_V_A5AIJG67OrBImC/pubhtml" target="_blank"&gt;in Google Docs&lt;/a&gt;), listing all attributes of all blends so that you can filter out what you need. Decaffeinated varieties are highlighted, because that's not real coffee 😁</description><author>Subclassed</author><pubDate>Mon, 16 Apr 2018 22:30:23 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/04/nespresso-blends-comprehensive.html</guid></item><item><title>Sloc Cloc and Code - What happened on the way to faster Cloc</title><link>https://boyter.org/posts/sloc-cloc-code/</link><description>&lt;h3 id="it-started-by-wanting-to-write-a-code-counter-that-would-be-faster-than-cloc"&gt;It started by wanting to write a code counter that would be faster than cloc&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Update 2019-03-13&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is now part of a series of blog posts about &lt;code&gt;scc&lt;/code&gt; Sloc Cloc and Code which has now been optimised to be the fastest code counter for almost every workload. Read more about it at the following links.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;Sloc Cloc and Code - What happened on the way to faster Cloc 2018-04-16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-revisited/"&gt;Sloc Cloc and Code Revisited - A focus on accuracy 2018-08-28&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance/"&gt;Sloc Cloc and Code Revisited - Optimizing an already fast Go application 2018-09-19&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-performance-update/"&gt;Sloc Cloc and Code a Performance Update 2019-01-09&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://boyter.org/posts/sloc-cloc-code-badges/"&gt;Sloc Cloc and Code Badges for Github/Bitbucket/Gitlab&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;TL/DR&lt;/strong&gt;&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Mon, 16 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://boyter.org/posts/sloc-cloc-code/</guid></item><item><title>Fun With Machine Learning</title><link>https://rjp.is/blogging/posts/fun-with-machine-learning/</link><description>In which we train a neural network.</description><author>infrequent oscillations</author><pubDate>Wed, 11 Apr 2018 16:33:59 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/fun-with-machine-learning/</guid></item><item><title>Highlands Festival of Speed 2018</title><link>https://smcleod.net/2018/04/highlands-festival-of-speed-2018/</link><description>&lt;p&gt;Last weekend I headed to New Zealand and marshalled at the &lt;a href="https://www.highlands.co.nz/events/highlands-festival-of-speed-2018/"&gt;Highlands Festival of Speed&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Highlands Festival of Speed is a weekend packed with some of the best modern classic racing you will see in New Zealand. Featuring the Pre 65 Racing, Mainland Muscle, Formula Libre, South Island Porsche, OSCA, Highlands Modern Classics/Nostalgic Classics and the Highlands Sprint Series. This is a weekend of true blue Kiwi racing starring some of New Zealand&amp;rsquo;s most well known racing legends.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Wed, 11 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/04/highlands-festival-of-speed-2018/</guid></item><item><title>How not to make an april fools joke</title><link>https://tomforb.es/blog/how-not-to-make-an-april-fools-joke/</link><description>Picture the scene. You’ve recently installed the awesome Lineage OS on your android device and are enjoying it so far. You install an update, it all goes smoothly, but upon restarting you are presented with this notification: What You press on the notification and you’re taken to the Lineage changel...</description><author>Tom Forbes</author><pubDate>Sun, 08 Apr 2018 03:00:00 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/how-not-to-make-an-april-fools-joke/</guid></item><item><title>Vignettes 3</title><link>https://rjp.is/blogging/posts/vignettes-3/</link><description>Vignettes for Black Sheep, 2006</description><author>infrequent oscillations</author><pubDate>Fri, 06 Apr 2018 23:11:20 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/vignettes-3/</guid></item><item><title>Quick Guide to setup your React + Typescript Storybook Design System</title><link>https://www.swyx.io/quick-guide-to-setup-your-react--typescript-storybook-design-system-1c51</link><description>&lt;p&gt;a no-bs guide to set up your new React and Typescript Design System powered by Storybook!&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Thu, 05 Apr 2018 20:58:13 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/quick-guide-to-setup-your-react--typescript-storybook-design-system-1c51</guid></item><item><title>Try React Suspense In 5 Minutes</title><link>https://www.swyx.io/how-to-try-react-suspense-in-5-minutes-474c</link><description>&lt;hr /&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 04 Apr 2018 00:39:13 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/how-to-try-react-suspense-in-5-minutes-474c</guid></item><item><title>Source Code for Life v0.1</title><link>https://www.swyx.io/source-code-for-life-v01-3pal</link><description>&lt;p&gt;Compiled Insights for Infinite Learners&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Mon, 02 Apr 2018 00:40:54 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/source-code-for-life-v01-3pal</guid></item><item><title>React Suspense Q&amp;amp;A</title><link>https://www.swyx.io/react-suspense-qa-28lc</link><description>&lt;p&gt;a friendly cheat sheet for those wondering what React Suspense is and if they should care&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Wed, 28 Mar 2018 00:02:17 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/react-suspense-qa-28lc</guid></item><item><title>Vignettes redux</title><link>https://rjp.is/blogging/posts/vignettes-redux/</link><description>In which we summarise some films through subtitle actions.</description><author>infrequent oscillations</author><pubDate>Tue, 27 Mar 2018 00:01:20 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/vignettes-redux/</guid></item><item><title>Appstores need a Trial Mode</title><link>http://blog.pythonaro.com/2018/03/appstores-need-trial-mode.html</link><description>&lt;p&gt;I've been looking for a while for a Windows-native Twitter client that could sync with my other non-Windows devices (&lt;abbr title="also known as"&gt;aka&lt;/abbr&gt; "supporting TweetMarker"). I've found one that claims to do that, &lt;a href="https://www.microsoft.com/store/productId/9NBLGGH62LKC"&gt;Tweet It!&lt;/a&gt;, but there is a problem: it costs £3.5 upfront. That's a relatively high amount of money to throw down a well hoping that my wish will come true. However, because this feature is so rare, &lt;i&gt;if it worked&lt;/i&gt; I'd be happy to pay three times as much, no questions asked. I just have no way to find out.&lt;/p&gt;

&lt;p&gt;Appstores need a simple Trial Mode. All the current hacks (In-App-Purchases, subscriptions, refunds etc) are just that, clumsy workarounds to this glaring omission, which is why app prices are so squeezed down - to the chagrin of indie developers. Trial Mode would also bring huge collateral benefits like reducing reliance on SaaS services (something that Microsoft in particular should relish) and creating viable alternatives to the free-to-play bubble that has turned online gaming into a socially-accepted form of gambling addiction.&lt;/p&gt;
&lt;p&gt;I doubt Apple will ever introduce Trial Mode - they are the dominant player and have little incentive to change the rules; and Android is a far west where the Play Store is almost irrelevant. But Microsoft should experiment with something like this, while the Windows Store is still young and evolving. Both developers and users would love it, they have been asking for something like this for years.&lt;/p&gt;</description><author>Subclassed</author><pubDate>Mon, 26 Mar 2018 10:00:12 GMT</pubDate><guid isPermaLink="true">http://blog.pythonaro.com/2018/03/appstores-need-trial-mode.html</guid></item><item><title>Book Review: ANSI Common Lisp</title><link>http://notes.eatonphil.com/book-review-ansi-common-lisp.html</link><description>&lt;h4 id="score:-4.5-/-5"&gt;Score: 4.5 / 5&lt;/h4&gt;&lt;p&gt;Paul Graham and his editor(s) are excellent. His prose is light and
easy to follow. The only awkward component of the book's organization
is that he tends to use a concept one section before explicitly
introducing and defining that concept. I'm not sure yet if this is a
good or bad thing.&lt;/p&gt;
&lt;h3 id="as-a-learning-resource"&gt;As a learning resource&lt;/h3&gt;&lt;p&gt;Among books recommended to potential Lispers, &lt;em&gt;ANSI Common Lisp&lt;/em&gt; is
typically written off. Graham's style of Lisp is called
"non-idiomatic". That's fair, both &lt;em&gt;ANSI Common Lisp&lt;/em&gt; and &lt;em&gt;On Lisp&lt;/em&gt;
feature aspects of Common Lisp that lend themselves to functional
programming. And as those of you who've read &lt;em&gt;Practical Common Lisp&lt;/em&gt;
know, Common Lisp (unlike Scheme) was not designed to be a functional
programming language. Ultimately &lt;em&gt;ANSI Common Lisp&lt;/em&gt; covers the same
topics &lt;em&gt;Practical Common Lisp&lt;/em&gt; does, if not more. But &lt;em&gt;ANSI Common
Lisp&lt;/em&gt; is better written, in less space, and with shorter examples.&lt;/p&gt;
&lt;p&gt;I'm impressed at Graham's ability to summarize. There is a graphic
illustrating symbols as a structure composed of a name, a value, a
function, a package, and a property list. Although other resources
(books and otherwise) mention symbols as having one or more of these
components, his graphic was the first representation that clicked for
me. He also provides clarity about packages being namespaces for
&lt;em&gt;names&lt;/em&gt; (symbols) not objects or functions.&lt;/p&gt;
&lt;p&gt;And toward the end of the book, there is a discussion on the
"instance" abstraction (relative to the class definitions themselves)
being more powerful than plain "objects" that carry around methods
themselves. This has been the single most useful discussion on the
implementation of object-oriented constructs I've read yet.&lt;/p&gt;
&lt;h3 id="digression-on-practical-common-lisp"&gt;Digression on Practical Common Lisp&lt;/h3&gt;&lt;p&gt;&lt;em&gt;Practical Common Lisp&lt;/em&gt; is often called the best introduction to
Common Lisp. After reading both, I'd give &lt;em&gt;Practical Common Lisp&lt;/em&gt;
second place or call it a tie. The issue with &lt;em&gt;Practical Common Lisp&lt;/em&gt;
is that it takes too long to get anywhere and the practical chapters
themselves are just as much a slog. And for as big as it is,
&lt;em&gt;Practical Common Lisp&lt;/em&gt; still doesn't include some major (potentially
confusing) aspects of "modern" Common Lisp like ASDF, Quicklisp,
production deployment strategies, etc.&lt;/p&gt;
&lt;p&gt;Even after having read &lt;em&gt;Practical Common Lisp&lt;/em&gt; I wasn't really clear
how to pull together all the libraries I needed to get anything real
done (e.g. scripting against an HTTP API or interacting with a SQL
database). This is not to say that &lt;em&gt;Practical Common Lisp&lt;/em&gt; is a bad
book, it is a good book. But I definitely don't recommend reading it
without also reading &lt;em&gt;ANSI Common Lisp&lt;/em&gt;. And regardless, there are
still a few of those modern concepts neither book covers.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sun, 25 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/book-review-ansi-common-lisp.html</guid></item><item><title>OCaml Speedrun! 🐫🐪</title><link>https://www.swyx.io/ocaml-speedrun-3f7g</link><description>&lt;p&gt;a guided walk through Jane Street's OCaml workshop&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 24 Mar 2018 23:11:35 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/ocaml-speedrun-3f7g</guid></item><item><title>An update on Apple Watch</title><link>https://rjp.is/blogging/posts/watch-update/</link><description>In which we consider our update.</description><author>infrequent oscillations</author><pubDate>Fri, 23 Mar 2018 02:08:09 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/watch-update/</guid></item><item><title>Migration to Hugo</title><link>https://rjp.is/blogging/posts/migration-to-hugo/</link><description>In which we migrate to Hugo.</description><author>infrequent oscillations</author><pubDate>Thu, 22 Mar 2018 11:12:00 GMT</pubDate><guid isPermaLink="true">https://rjp.is/blogging/posts/migration-to-hugo/</guid></item><item><title>Same great Postgres with a new player in town</title><link>/2018/03/20/same-great-postgres-new-player-in-town/</link><description>&lt;p&gt;Many of us have known how great &lt;a href="http://www.craigkerstiens.com/2012/04/30/why-postgres/"&gt;Postgres&lt;/a&gt; was for &lt;a href="http://www.craigkerstiens.com/2017/04/30/why-postgres-five-years-later/"&gt;years&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;In fact I recall a conversation with some sales engineers about 6 years ago that previously worked for a large database vendor that really no one likes down in Redwood City. They were remarking how the biggest threat to them was Postgres. At first they were able to just brush it off saying it was open source and no real database could be open source. Then as they dug in they realized there was more there than most knew about and they would have to continually be finding ways to discredit it in sales conversations. Well it doesn&amp;rsquo;t look like those SEs or the rest of that company was too successful.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Postgres is certainly &lt;a href="https://www.infoworld.com/article/3261571/database/how-postgresql-just-might-replace-your-oracle-database.html"&gt;having it&amp;rsquo;s moment&lt;/a&gt;, and I personally don&amp;rsquo;t expect it to fade soon.&lt;/p&gt;
&lt;p&gt;An equally interesting shift I&amp;rsquo;ve watched from the outside has been Microsoft&amp;rsquo;s shift to support and engage with the &lt;a href="http://redmonk.com/sogrady/2017/09/28/microsoft-hiring/"&gt;open source movement&lt;/a&gt;. Personally that shift is extremely exciting to see, especially today as they announce their general availability of their &lt;a href="https://azure.microsoft.com/en-us/blog/announcing-general-availability-of-azure-database-services-for-mysql-and-postgresql/"&gt;Postgres&lt;/a&gt; offering. And with their announcement it looks they&amp;rsquo;re not just dabbling but shipping a very compelling offering, notably high availability is built-in which means they&amp;rsquo;re very much targetting production workloads. With their GA release there are a number of interesting boxes checked:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HIPPA, SOC, ISO compliances&lt;/li&gt;
&lt;li&gt;99.99% uptime SLA&lt;/li&gt;
&lt;li&gt;Available in 22 regions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Personally I&amp;rsquo;m looking forward to the new competition for Postgres users as it&amp;rsquo;ll make Postgres better and better for all. When I was at Heroku and was running product for Heroku Postgres 7 years ago we were the only large major provider. Today that landscape looks a lot different and it just means more choice and more quality if you want to run Postgres. So welcome Microsoft, I look forward to giving Azure Postgres a try.&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Tue, 20 Mar 2018 22:55:56 GMT</pubDate><guid isPermaLink="true">/2018/03/20/same-great-postgres-new-player-in-town/</guid></item><item><title>Flash Storage and SSD Failure Rate Update (March 2018)</title><link>https://smcleod.net/2018/03/flash-storage-and-ssd-failure-rate-update-march-2018/</link><description>&lt;p&gt;It was almost 3 years ago that my open source storage project went into production. In that time it&amp;rsquo;s been running 24/7 serving as highly available solid state storage for hundreds of VMs and several virtualisation clusters across our two main sites.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m happy to report that the clusters have been operating very successfully since their conception.&lt;/p&gt;
&lt;p&gt;Since moving away from proprietary &amp;lsquo;black box&amp;rsquo; vendor SANs, we haven&amp;rsquo;t had a single SAN issue, storage outage.&lt;/p&gt;</description><author>smcleod.net</author><pubDate>Tue, 20 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/03/flash-storage-and-ssd-failure-rate-update-march-2018/</guid></item><item><title>Introduction to MobX 4 for React/Redux Developers</title><link>https://www.swyx.io/introduction-to-mobx-4-for-reactredux-developers-3k07</link><description>&lt;p&gt;an introduction to mobx 4 for people coming from react and redux&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 17 Mar 2018 04:19:23 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/introduction-to-mobx-4-for-reactredux-developers-3k07</guid></item><item><title>Building the Fetchr Data Science Infra on AWS with Presto and Airflow</title><link>https://bytepawn.com/fetchr-airflow.html</link><description>&lt;p&gt;We used Hive/Presto on AWS together with Airflow to rapidly build out the Data Science Infrastructure at Fetchr in less than 6 months.&lt;br /&gt;&lt;br /&gt;&lt;img alt="Warehouse DAG" src="/images/warehouse-dag.png" style="width: 400px;" /&gt;&lt;/p&gt;</description><author>Bytepawn - Marton Trencseni</author><pubDate>Wed, 14 Mar 2018 01:00:00 GMT</pubDate><guid isPermaLink="true">https://bytepawn.com/fetchr-airflow.html</guid></item><item><title>A quick comparison between different Go file walk implementations</title><link>https://boyter.org/2018/03/quick-comparison-go-file-walk-implementations/</link><description>&lt;p&gt;&lt;strong&gt;UPDATE&lt;/strong&gt; The below is here for historical reasons, but since 2021 very out of date. See this post &lt;a href="https://engineering.kablamo.com.au/posts/2021/quick-comparison-between-go-file-walk-implementations"&gt;https://engineering.kablamo.com.au/posts/2021/quick-comparison-between-go-file-walk-implementations&lt;/a&gt; for an updated comparison.&lt;/p&gt;
&lt;p&gt;Whats the fastest way to get all the names of all files in a directory using Go? I had a feeling that the native walk might not be the fastest way to do it. A quick search showed that several projects claimed to be faster. Since the &lt;a href="https://github.com/boyter/scc"&gt;application&lt;/a&gt; I am currently working on needs a high performance scanner I thought I would try the main ones out.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Sun, 11 Mar 2018 11:58:51 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2018/03/quick-comparison-go-file-walk-implementations/</guid></item><item><title>Collection of my favorite optimization posts and articles</title><link>https://boyter.org/2018/03/collection-favorite-optimization-posts-articles/</link><description>&lt;p&gt;A collection of my favorite posts to read and re-read about optimizing code to an extreme. Unlikely that I will ever need to go to the extremes that these very talented individuals go to but its nice to learn the techniques.&lt;/p&gt;
&lt;p&gt;In no particular order.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Announcement of Ripgrep a tool for searching code. Brilliantly written with benchmarks and analysis to explain what is happening for each &lt;a href="https://blog.burntsushi.net/ripgrep/"&gt;https://blog.burntsushi.net/ripgrep/&lt;/a&gt; the HN comments about it are worth reading as well &lt;a href="https://news.ycombinator.com/item?id=12564442"&gt;https://news.ycombinator.com/item?id=12564442&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How Mailinator compresses email by ~90%. Very interesting use of some creative thinking and LRU caches &lt;a href="https://mailinator.blogspot.com.au/2012/02/how-mailinator-compresses-email-by-90.html"&gt;https://mailinator.blogspot.com.au/2012/02/how-mailinator-compresses-email-by-90.html&lt;/a&gt; some decent HN comments as well &lt;a href="https://news.ycombinator.com/item?id=3617074"&gt;https://news.ycombinator.com/item?id=3617074&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Searching 1TB/sec: Systems Engineering Before Algorithms. Explains how using brute force solutions to solve problems can be viable if you have enough brute and can write a tight inner loop. &lt;a href="http://blog.scalyr.com/2014/05/searching-20-gbsec-systems-engineering-before-algorithms/"&gt;http://blog.scalyr.com/2014/05/searching-20-gbsec-systems-engineering-before-algorithms/&lt;/a&gt; the HN comments for this one are also worth reading &lt;a href="https://news.ycombinator.com/item?id=7715025"&gt;https://news.ycombinator.com/item?id=7715025&lt;/a&gt; and &lt;a href="https://news.ycombinator.com/item?id=11783483"&gt;https://news.ycombinator.com/item?id=11783483&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The Treacherous Optimization. Post about making search faster by firstly comparing to grep and analysis of how grep achieves its speed. Very amusing in the way it is written as well. &lt;a href="http://ridiculousfish.com/blog/posts/old-age-and-treachery.html"&gt;http://ridiculousfish.com/blog/posts/old-age-and-treachery.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Another from Paul Tyma of Mailinator but less about Mailinator and more about how cache misses on the CPU can impact your performance. &lt;a href="https://mailinator.blogspot.com.au/2010/02/how-i-sped-up-my-server-by-factor-of-6.html"&gt;https://mailinator.blogspot.com.au/2010/02/how-i-sped-up-my-server-by-factor-of-6.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Another from Paul (that guy is seriously smart) about the architecture of Mailinator and some tricks it employs to run on a single server (at the time). &lt;a href="https://mailinator.blogspot.com.au/2007/01/architecture-of-mailinator.html"&gt;https://mailinator.blogspot.com.au/2007/01/architecture-of-mailinator.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Improving spelling correction algorithm. Has code as well which is useful to learn from. &lt;a href="http://blog.faroo.com/2012/06/07/improved-edit-distance-based-spelling-correction/"&gt;http://blog.faroo.com/2012/06/07/improved-edit-distance-based-spelling-correction/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Profiling Ag. Writing My Own Scandir. Written by the author of ag the code searcher. &lt;a href="https://geoff.greer.fm/2012/09/03/profiling-ag-writing-my-own-scandir/"&gt;https://geoff.greer.fm/2012/09/03/profiling-ag-writing-my-own-scandir/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Another Ag post about adding threads into Ag to improve searching performance. &lt;a href="https://geoff.greer.fm/2012/09/07/the-silver-searcher-adding-pthreads/"&gt;https://geoff.greer.fm/2012/09/07/the-silver-searcher-adding-pthreads/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;LMAX Distruptor interesting collection of posts about how it works &lt;a href="https://lmax-exchange.github.io/disruptor/"&gt;https://lmax-exchange.github.io/disruptor/&lt;/a&gt; the HN comments on the Martin Fowler blog are worth looking at &lt;a href="https://news.ycombinator.com/item?id=3173993"&gt;https://news.ycombinator.com/item?id=3173993&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Regular Expression Matching with a Trigram Index or How Google Code Search Worked. &lt;a href="https://swtch.com/~rsc/regexp/regexp4.html"&gt;https://swtch.com/~rsc/regexp/regexp4.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Excellent explanation of branch prediction and its impact on how quickly your code can run. Ran into this once with searchcode and felt like a genius when I solved it. &lt;a href="https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array"&gt;https://stackoverflow.com/questions/11227809/why-is-it-faster-to-process-a-sorted-array-than-an-unsorted-array&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;More branch prediction, A brief history of branch prediction by Dan Luu &lt;a href="https://danluu.com/branch-prediction/"&gt;https://danluu.com/branch-prediction/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Branch prediction ahoy! &lt;a href="http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/"&gt;http://igoro.com/archive/fast-and-slow-if-statements-branch-prediction-in-modern-processors/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why Gnu Grep is fast &lt;a href="https://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html"&gt;https://lists.freebsd.org/pipermail/freebsd-current/2010-August/019310.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;How to write fast code &lt;a href="http://asserttrue.blogspot.com.au/2009/03/how-to-write-fast-code.html"&gt;http://asserttrue.blogspot.com.au/2009/03/how-to-write-fast-code.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Regular Expression Matching Can Be Simple And Fast (but is slow in Java, Perl, PHP, Python, Ruby, …) &lt;a href="https://swtch.com/%7Ersc/regexp/regexp1.html"&gt;https://swtch.com/%7Ersc/regexp/regexp1.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Why Writing Your Own Search Engine is Hard &lt;a href="https://queue.acm.org/detail.cfm?id=988407"&gt;https://queue.acm.org/detail.cfm?id=988407&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Effects of CPU caches &lt;a href="https://medium.com/@minimarcel/effect-of-cpu-caches-57db81490a7f"&gt;https://medium.com/@minimarcel/effect-of-cpu-caches-57db81490a7f&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Neon is the New Black: fast JPEG optimization on ARM server &lt;a href="https://blog.cloudflare.com/neon-is-the-new-black/"&gt;https://blog.cloudflare.com/neon-is-the-new-black/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Beware of cute optimizations bearing gifts. Optimisations made to a fast fuzzy file matcher in Vim &lt;a href="https://wincent.com/blog/optimization"&gt;https://wincent.com/blog/optimization&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Go code refactoring : the 23x performance hunt &lt;a href="https://medium.com/@val_deleplace/go-code-refactoring-the-23x-performance-hunt-156746b522f7"&gt;https://medium.com/@val_deleplace/go-code-refactoring-the-23x-performance-hunt-156746b522f7&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Shameless self promotion but what I went through when building scc which is a code counter similar to cloc &lt;a href="https://boyter.org/posts/sloc-cloc-code/"&gt;https://boyter.org/posts/sloc-cloc-code/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Built for Speed: Custom Parser for Regex at Scale &lt;a href="https://blog.scalyr.com/2018/08/custom-regex-parser/"&gt;https://blog.scalyr.com/2018/08/custom-regex-parser/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Gallery of Processor Cache Effects &lt;a href="http://igoro.com/archive/gallery-of-processor-cache-effects/"&gt;http://igoro.com/archive/gallery-of-processor-cache-effects/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Making the obvious code fast &lt;a href="https://jackmott.github.io/programming/2016/07/22/making-obvious-fast.html"&gt;https://jackmott.github.io/programming/2016/07/22/making-obvious-fast.html&lt;/a&gt; with interesting HN comments &lt;a href="https://news.ycombinator.com/item?id=19680595"&gt;https://news.ycombinator.com/item?id=19680595&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Optimizing M3: How Uber Halved Our Metrics Ingestion Latency by (Briefly) Forking the Go Compiler &lt;a href="https://eng.uber.com/optimizing-m3/"&gt;https://eng.uber.com/optimizing-m3/&lt;/a&gt; &lt;a href="https://news.ycombinator.com/item?id=19692451"&gt;https://news.ycombinator.com/item?id=19692451&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Linux Load Averages: Solving the Mystery &lt;a href="http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html"&gt;http://www.brendangregg.com/blog/2017-08-08/linux-load-averages.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The state of caching in Go &lt;a href="https://blog.dgraph.io/post/caching-in-go/"&gt;https://blog.dgraph.io/post/caching-in-go/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Introducing Ristretto: A High-Performance Go Cache &lt;a href="https://blog.dgraph.io/post/introducing-ristretto-high-perf-go-cache/"&gt;https://blog.dgraph.io/post/introducing-ristretto-high-perf-go-cache/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Building a Vectorized SQL Engine. A very good read about how CPU&amp;rsquo;s work and data layouts affect it &lt;a href="https://www.cockroachlabs.com/blog/how-we-built-a-vectorized-sql-engine/"&gt;https://www.cockroachlabs.com/blog/how-we-built-a-vectorized-sql-engine/&lt;/a&gt; with Hacker News comments &lt;a href="https://news.ycombinator.com/item?id=21516322"&gt;https://news.ycombinator.com/item?id=21516322&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Writing a fast cache service in Go &lt;a href="https://allegro.tech/2016/03/writing-fast-cache-service-in-go.html"&gt;https://allegro.tech/2016/03/writing-fast-cache-service-in-go.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;qgrep internals &lt;a href="https://zeux.io/2019/04/20/qgrep-internals/"&gt;https://zeux.io/2019/04/20/qgrep-internals/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Scaling our Spreadsheet Engine from Thousands to Billions of Cells - From Maps to Arrays &lt;a href="https://www.causal.app/blog/scaling"&gt;https://www.causal.app/blog/scaling&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Will attempt to keep this list up to date as I find other content that really impresses me.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Fri, 09 Mar 2018 00:34:02 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2018/03/collection-favorite-optimization-posts-articles/</guid></item><item><title>Starting a minimal Common Lisp project</title><link>http://notes.eatonphil.com/starting-a-minimal-common-lisp-project.html</link><description>&lt;p&gt;If you've only vaguely heard of Lisp before or studied Scheme in
school, Common Lisp is nothing like what you'd expect. While
functional programming is all the rage in Scheme, Common Lisp was
"expressly designed to be a real-world engineering language rather
than a theoretically 'pure' language" (&lt;a href="http://www.gigamonkeys.com/book/introduction-why-lisp.html"&gt;Practical Common
Lisp&lt;/a&gt;).
Furthermore, &lt;a href="http://sbcl.org/"&gt;SBCL&lt;/a&gt; -- a popular implementation --
is a highly optimized compiler that is competitive with
&lt;a href="https://benchmarksgame.alioth.debian.org/u64q/lisp.html"&gt;Java&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="building-blocks"&gt;Building blocks&lt;/h3&gt;&lt;p&gt;Common Lisp symbols, imagine "first-class" variables/labels, are
encapsulated in namespaces called packages. However packages don't
account for organization across directories, among other things. So
while packages are a part of the core Common Lisp language, the
"cross-directory" organizational structure is managed by the
(all-but-standard) &lt;a href="https://github.com/fare/asdf"&gt;ASDF&lt;/a&gt; "systems". You
can think of packages as roughly similar to modules in Python whereas
systems in ASDF are more like packages in Python.&lt;/p&gt;
&lt;p&gt;ASDF does not manage non-local dependencies. For that we use
&lt;a href="https://www.quicklisp.org/beta/"&gt;Quicklisp&lt;/a&gt;, the defacto package
manager. ASDF should come bundled with your Common Lisp installation,
which I'll assume is SBCL (not that it matters). Quicklisp does not
come bundled.&lt;/p&gt;
&lt;h3 id="getting-quicklisp"&gt;Getting Quicklisp&lt;/h3&gt;&lt;p&gt;You can follow the notes on the Quicklisp
&lt;a href="https://www.quicklisp.org/beta/"&gt;site&lt;/a&gt; for installation, but the
basic gist is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;https://beta.quicklisp.org/quicklisp.lisp
$&lt;span class="w"&gt; &lt;/span&gt;sbcl&lt;span class="w"&gt; &lt;/span&gt;--load&lt;span class="w"&gt; &lt;/span&gt;quicklisp.lisp
...
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;quicklisp-quickstart:install&lt;span class="o"&gt;)&lt;/span&gt;
...
*&lt;span class="w"&gt; &lt;/span&gt;^D
$&lt;span class="w"&gt; &lt;/span&gt;sbcl&lt;span class="w"&gt; &lt;/span&gt;--load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;~/quicklisp/setup.lisp&amp;quot;&lt;/span&gt;
...
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ql:add-to-init-file&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h3 id="a-minimal-package"&gt;A minimal package&lt;/h3&gt;&lt;p&gt;Now we're ready to get started. Create a directory using the name of
the library you'd like to package. For instance, I'll create a
"cl-docker" directory for my Docker wrapper library. Then create a
file using the same name in the directory with the ".asd" suffix:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/projects
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;cl-docker
$&lt;span class="w"&gt; &lt;/span&gt;touch&lt;span class="w"&gt; &lt;/span&gt;cl-docker/cl-docker.asd
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It is important for the ".asd" file to share the same name as the
directory because ASDF will look for it in that location (by default).&lt;/p&gt;
&lt;p&gt;Before we get too far into packaging, let's write a function we'd like
to export from this library. Edit "cl-docker/docker.lisp" (this name does
not matter) and add the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;uiop:run-program&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;docker&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ps&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cl-ppcre:split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(\\n+)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;collect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cl-ppcre:split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(\\s\\s+)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This uses a portable library, "uiop", that ASDF exposes by default (we
won't need to explicitly import this anywhere because the package is
managed by ASDF). It will run the command "docker ps" in a subprocess
and return the output as a string. Then we use the regex split
function from the "cl-ppcre" library to split the output first into
lines, take all but the first line, and split the lines up based one
two or more whitespace characters.&lt;/p&gt;
&lt;p&gt;Next let's define the package (think module in Python) by editing
"cl-docker/package.lisp" (this name also does not matter):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defpackage&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cl-docker&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;cl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:import-from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:cl-ppcre&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:split&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:ps&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we state the package's name, say that we want to import all
Common Lisp base symbols into the package, say we want to import the
"split" symbol from the "cl-ppcre" package, and say we only want to
export our "ps" function.&lt;/p&gt;
&lt;p&gt;At this point we must also declare within the "cl-docker/docker.lisp"
file that it is a part of this package:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;in-package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:cl-docker&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;defun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ps&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;uiop:run-program&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;docker&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ps&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:output&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:string&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;loop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cl-ppcre:split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(\\n+)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nv"&gt;collect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;cl-ppcre:split&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;(\\s\\s+)&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;line&lt;/span&gt;&lt;span class="p"&gt;))))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Next let's define the system (ASDF-level, similar to a package in Python)
in "cl-docker/cl-docker.asd":&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;defsystem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;:cl-docker&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ss"&gt;:depends-on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:cl-ppcre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ss"&gt;:serial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;t&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="ss"&gt;:components&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="ss"&gt;:file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;package&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;                 &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;docker&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This defines all the pieces of the system for ASDF: the system name,
the package definition and the component of the package
("cl-docker/docker.lisp"), and tells ASDF to make the "cl-ppcre"
system on disk available to us. We also tell ASDF to process the
components in the order we specified (otherwise it will pick an order
that may not be what we want).&lt;/p&gt;
&lt;p&gt;In preparation for times when we don't have the "cl-ppcre" system (or
any other dependencies) on disk, we always load the system indirectly
through Quicklisp (rather than directly via ASDF) so Quicklisp can
fetch any missing dependencies from its repository of systems.&lt;/p&gt;
&lt;p&gt;But before then -- unless you put this directory in "~/common-lisp" --
you'll need to register the directory containing the directory of your
system definitions so ASDF (and Quicklisp) know where to look if you
ask to load this system.&lt;/p&gt;
&lt;p&gt;To do this, add a ".conf" file to
"~/.config/common-lisp/source-registry.conf.d/" and add the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/path/to/dir/containing/system/dir&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;So if you had a repo called "cl-docker" in your "~/projects" directory
that contained the "cl-docker" directory we previously created (that,
in turn, contains the "cl-docker.asd", "package.lisp", and
"docker.lisp" files) then you might create
"~/.config/common-lisp/source-registry.conf.d/1-cl-docker.conf" and
add:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:tree&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;~/projects/cl-docker&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;h4 id="using-the-system"&gt;Using the system&lt;/h4&gt;&lt;p&gt;Now you can use the library from anywhere on your computer. Enter a
Common Lisp REPL and tell Quicklisp to load the system (and download
any non-local dependencies):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;sbcl
...
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;ql:quickload&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cl-docker&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
To&lt;span class="w"&gt; &lt;/span&gt;load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cl-docker&amp;quot;&lt;/span&gt;:
&lt;span class="w"&gt;  &lt;/span&gt;Load&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ASDF&lt;span class="w"&gt; &lt;/span&gt;system:
&lt;span class="w"&gt;    &lt;/span&gt;cl-docker
&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Loading&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cl-docker&amp;quot;&lt;/span&gt;
..................................................
&lt;span class="o"&gt;[&lt;/span&gt;package&lt;span class="w"&gt; &lt;/span&gt;cl-docker&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;cl-docker&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
*&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;cl-docker:ps&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And that's it!&lt;/p&gt;
&lt;p&gt;For the complete source of this example package, check out this
&lt;a href="https://gist.github.com/eatonphil/59cdfeb4826c7a12a07d7055f6817a56"&gt;Gist&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="in-conclusion"&gt;In conclusion&lt;/h3&gt;&lt;p&gt;Common Lisp is easy to work with, the packages are many and mature.
Configuring an ASDF package is even simpler than configuring a Python
"setup.py". I didn't demonstrate pinning versions of dependencies in
ASDF, but &lt;a href="https://stackoverflow.com/a/21663603/1507139"&gt;of course&lt;/a&gt;
you can do that too. If any of this -- as simple as it is -- seems
tedious, you can also use Zach Beane's (creator of Quicklisp)
&lt;a href="http://xach.livejournal.com/278047.html"&gt;quickproject&lt;/a&gt; tool to build
out the structure for you.&lt;/p&gt;
&lt;h3 id="resources-for-common-lisp"&gt;Resources for Common Lisp&lt;/h3&gt;&lt;p&gt;You must read &lt;a href="http://www.gigamonkeys.com/book/"&gt;Practical Common
Lisp&lt;/a&gt;. It is freely available
online. It is one of the best resources I keep referring to in
dealing with simple issues (as a new Lisper, I stumble on a lot of
simple issues).&lt;/p&gt;
&lt;p&gt;Paul Graham's &lt;a href="http://www.paulgraham.com/onlisp.html"&gt;On Lisp&lt;/a&gt; is also
a must-read when you want to get a better understanding of macros in
Lisp. It will help you out with macros in Scheme too. This book is
freely available online, but out of print physically. I sent
&lt;a href="https://www.lulu.com/"&gt;Lulu&lt;/a&gt; the PDF and I received my physical copy
for under $20 (including shipping).&lt;/p&gt;
&lt;p&gt;I'm currently making my way through &lt;a href="http://www.cs.cmu.edu/Groups/AI/html/cltl/cltl2.html"&gt;Common Lisp the Language, 2nd
Edition&lt;/a&gt; which I
believe is also freely available online. However I don't really
recommend this unless you are interested in implementing Common Lisp
or are dying to learn the standard library (not a bad idea).&lt;/p&gt;
&lt;p&gt;Finally, Peter Norvig's &lt;a href="https://github.com/norvig/paip-lisp"&gt;Paradigms of Artificial Intelligence
Programming&lt;/a&gt; just recently became
freely available online. I haven't yet read it but I'm queuing it
up. Don't let the title scare you, apparantly it is primarily
considered a practical guide to Common Lisp around
old-school/classical AI that isn't supposed to encumber.&lt;/p&gt;
&lt;p class="note"&gt;
  It
  was &lt;a href="https://twitter.com/HexstreamSoft/status/971419419862847494"&gt;pointed
  out&lt;/a&gt; on Twitter that Paul
  Graham's &lt;a href="http://www.paulgraham.com/acl.html"&gt;ANSI Common
  Lisp&lt;/a&gt; and the
  &lt;a href="http://www.lispworks.com/documentation/lw70/CLHS/Front/Contents.htm"&gt;CLHS&lt;/a&gt;
  are probably better resources for the Common Lisp that exists today
  than Common Lisp the Language 2. CLtL2 is pre-standard.
&lt;/p&gt;&lt;p&gt;Additionally, the &lt;a href="http://lispcookbook.github.io/cl-cookbook/"&gt;Common Lisp
Cookbook&lt;/a&gt; is a great
resource for Common Lisp recipes. It's been around since 2004 (on
Sourceforge) but has been pretty active recently and has been revived
on Github pages.&lt;/p&gt;
&lt;h3 id="on-scheme"&gt;On Scheme&lt;/h3&gt;&lt;p&gt;I've done one or two unremarkable web prototypes in &lt;a href="https://www.call-cc.org/"&gt;Chicken
Scheme&lt;/a&gt;, an R5RS/R7RS Scheme implementation.
I don't think Chicken Scheme is the best bet for the web (I'm mostly
biased to this topic) because it has no native-thread support and
there are lighter interpreters out there that are easier to embed
(e.g. in nginx). Chicken Scheme's "niche" is being a generally
high-quality implementation with a great &lt;a href="http://wiki.call-cc.org/chicken-projects/egg-index-4.html"&gt;collection of 3rd-party
libraries&lt;/a&gt;,
but it is also not the
&lt;a href="https://ecraven.github.io/r7rs-benchmarks/"&gt;fastest&lt;/a&gt; Scheme you could
choose.&lt;/p&gt;
&lt;p&gt;I've worked on a larger web prototype -- a Github issue reporting app
-- in &lt;a href="https://racket-lang.org/"&gt;Racket&lt;/a&gt;, a derivative of Scheme
R6RS. And I've blogged
&lt;a href="http://notes.eatonphil.com/walking-through-a-basic-racket-web-service.html"&gt;favorably&lt;/a&gt;
about Racket. It is a
&lt;a href="https://ecraven.github.io/r7rs-benchmarks/"&gt;high-performance&lt;/a&gt;
interpreter with a JIT compiler, has thread support, and is also well
known for its collection of &lt;a href="https://pkgs.racket-lang.org/"&gt;3rd-party
libaries&lt;/a&gt;. However the Racket ecosystem
&lt;a href="https://fare.livejournal.com/188429.html"&gt;suffers&lt;/a&gt; from the same
issues Haskell's does: libraries and bindings are primarily
proof-of-concept only; missing documentation, tests and use. Trying to
render "templatized" HTML (like Jinja allows for in Flask) without
using S-exp-based syntax was a nightmare.  (Read: there's space for
someone to write a good string templating library.)&lt;/p&gt;
&lt;h4 id="sorry,-racket"&gt;Sorry, Racket&lt;/h4&gt;&lt;p&gt;Last point on Racket (because it really is worth looking into),
debugging in that Github issue project was not fun. The backtraces
were mostly useless. Naively I assume this may have to do with the way
Racket optimizes and rewrites functions. I was often left with zero
context to find and correct my errors. But it could very well be I
was making poor use of Racket.&lt;/p&gt;
&lt;h4 id="on-the-other-hand"&gt;On the other hand&lt;/h4&gt;&lt;p&gt;Common Lisp (its implementations and ecosystem) seems more robust and
developed. SBCL, with it's great performance and native-thread
support, is a promising candidate for backend web development.&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;I wrote a post on putting together a Common Lisp project. It's easy! I also included some of my favorite CL books and a digression on Scheme. &lt;a href="https://t.co/2LEDoFnAjk"&gt;https://t.co/2LEDoFnAjk&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/commonlisp?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#commonlisp&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/lisp?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#lisp&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/scheme?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#scheme&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/971398435856371712?ref_src=twsrc%5Etfw"&gt;March 7, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Mon, 05 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/starting-a-minimal-common-lisp-project.html</guid></item><item><title>A Walkthrough of *that* React Suspense Demo</title><link>https://www.swyx.io/a-walkthrough-of-that-react-suspense-demo--4j6a</link><description>&lt;p&gt;Annotated commentary on the code behind the Movie search demo featuring React Suspense&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Fri, 02 Mar 2018 07:47:27 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/a-walkthrough-of-that-react-suspense-demo--4j6a</guid></item><item><title>Scaling Django Codebases at PyCon UK 2017</title><link>https://danpalmer.me/2018-03-02-scaling-django-codebases/</link><description>Four of us from the Thread engineering team went to PyCon UK again in September for the third year running, and I was lucky enough to have my talk selected.
At Thread we use Django for the backend of the main site which has grown to over 350 “apps”, and various members of the team have used the framework since not long after the initial public release.
I’ve learnt many tips, tricks, and best practices for keeping engineers productive on a codebase of this size from my colleagues over the years, and I shared the highlights with the Python community in September.</description><author>Dan Palmer</author><pubDate>Fri, 02 Mar 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://danpalmer.me/2018-03-02-scaling-django-codebases/</guid></item><item><title>Licensechecker. A command line application which identifies what software license things are under</title><link>https://boyter.org/2018/03/licensechecker-command-line-application-identifies-software-license/</link><description>&lt;p&gt;A simple blog post here to introduce a new command line tool licensechecker (lc), which is similar in purpose to the library Licensee &lt;a href="http://ben.balter.com/licensee/"&gt;http://ben.balter.com/licensee/&lt;/a&gt; which attempts to identify what software license(s) code is released under. lc itself is dual licensed under the MIT and Unlicense.&lt;/p&gt;
&lt;p&gt;Licensechecker (lc) was designed to be run either on your command line or using your CI tool of choice and produce either CSV, JSON, SPDX, Summary or CLI tabular or progress output with the option to write results to disk. It is reasonably fast and is cross platform with binaries for x64 versions of Linux, macOS and Windows. The build process also ensures that it builds on ARM and i386.&lt;/p&gt;</description><author>Ben E. C. Boyter</author><pubDate>Thu, 01 Mar 2018 09:24:29 GMT</pubDate><guid isPermaLink="true">https://boyter.org/2018/03/licensechecker-command-line-application-identifies-software-license/</guid></item><item><title>MicroFlo and IoT: measuring air quality</title><link>https://bergie.iki.fi/blog/microflo-particulate-sensors/</link><description>&lt;p&gt;Fine particulate matter is a serious issue in many cities around the world. In Europe, it is &lt;a href="https://ec.europa.eu/jrc/en/news/air-quality-atlas-europe-mapping-sources-fine-particulate-matter"&gt;estimated to cause&lt;/a&gt; 400.000 premature deaths per year. European Union has published standards on the matter, and warned several countries that haven’t been able to reach the safe limits.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Germany saw the highest number of deaths attributable to all air pollution sources, at 80,767. It was followed by the United Kingdom (64,351) and France (63,798). These are also the most populated countries in Europe. (source: &lt;a href="http://www.dw.com/en/air-pollution-kills-half-a-million-people-in-europe-eu-agency-reports/a-40920041"&gt;DW&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The associated health issues don’t come cheap: 20 billion euros per year on health costs alone.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;“To reduce this figure we need member states to comply with the emissions limits which they have agreed to,” Schinas said. “If this is not the case the Commission as guardian of the (founding EU) treaty will have to take appropriate action,” he added. (source: &lt;a href="https://phys.org/news/2018-01-eu-summons-france-germany-uk.html"&gt;phys.org&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One part of solving this issue is better data. Government-run measurement stations are quite sparse, and — in some countries — their published results can be unreliable. To solve this, &lt;a href="https://okfn.de/en/"&gt;Open Knowledge Foundation Germany&lt;/a&gt; started the &lt;a href="https://luftdaten.info/"&gt;luftdaten.info&lt;/a&gt; project to crowdsource air pollution data around the world.&lt;/p&gt;



&lt;p&gt;Last saturday we hosted a luftdaten.info workshop at &lt;a href="https://c-base.org/"&gt;c-base&lt;/a&gt;, and used the opportunity to build and deploy some particulate matter sensors. While &lt;a href="https://luftdaten.info/en/construction-manual/"&gt;luftdaten.info has a great build guide&lt;/a&gt; and we used their parts list, we decided to go with a &lt;a href="https://github.com/c-base/microflo-luftdaten"&gt;custom firmware&lt;/a&gt; built with MicroFlo and integrated with the existing IoT network at c-base.&lt;/p&gt;

&lt;p&gt;&lt;img alt="Building an air quality sensor" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/luftdaten-sensor-workshop2.jpg" /&gt;&lt;/p&gt;

&lt;h2 id="microflo-on-esp8266"&gt;MicroFlo on ESP8266&lt;/h2&gt;

&lt;p&gt;&lt;a href="http://microflo.org/"&gt;MicroFlo&lt;/a&gt; is a flow-based programming runtime targeting microcontrollers. Just like NoFlo graphs run inside a browser or Node.js, the MicroFlo graphs run on an Arduino or other compatible device. The result of a MicroFlo build is a firmware that can be flashed on a microcontroller, and which can be live-programmed using tools like &lt;a href="https://flowhub.io/iot/"&gt;Flowhub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;ESP8266 is an Arduino-compatible microcontroller with integrated WiFi chip. This means any sensors or actuators on the device can easily connect to other systems, like we do with &lt;a href="https://github.com/c-base/c-flo/tree/master/devices"&gt;lots of different sensors&lt;/a&gt; already at c-base.&lt;/p&gt;

&lt;p&gt;&lt;img alt="ESP8266 sensor in preparation" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/luftdaten-sensor-esp8266.jpg" /&gt;&lt;/p&gt;

&lt;p&gt;MicroFlo &lt;a href="https://github.com/microflo/microflo/blob/master/CHANGES.md#microflo-063"&gt;recently added&lt;/a&gt; a feature where Wifi-enabled MicroFlo devices can automatically connect with a MQTT message queue and expose their in/outports as queues there. This makes MicroFlo on an ESP8266 a fully-qualified &lt;a href="https://msgflo.org/"&gt;MsgFlo participant&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id="building-the-firmware"&gt;Building the firmware&lt;/h2&gt;

&lt;p&gt;We wanted to build a firmware that would periodically read both the DHT22 temperature and humidity sensor, and the SDS011 fine particulate sensor, even out the readings with a running median, and then send the values out at a specified interval. MicroFlo’s &lt;a href="https://github.com/microflo/microflo-core"&gt;core library&lt;/a&gt; already provided most of the building blocks, but we had to write &lt;a href="https://github.com/c-base/microflo-luftdaten/tree/master/components"&gt;custom components&lt;/a&gt; for dealing with the sensor hardware.&lt;/p&gt;

&lt;p&gt;Thankfully Arduino libraries existed for both sensors, and this was just a matter of wrapping those to the MicroFlo component interface.&lt;/p&gt;

&lt;p&gt;After the components were done, we could build the firmware &lt;a href="http://app.flowhub.io/#github/c-base/microflo-luftdaten"&gt;as a Flowhub graph&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://app.flowhub.io/#github/c-base/microflo-luftdaten"&gt;&lt;img alt="MicroFlo luftdaten graph" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/microflo-luftdaten-graph.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To verify the build we enabled &lt;a href="https://travis-ci.org/"&gt;Travis CI&lt;/a&gt; where we build the firmware both against the MicroFlo Arduino and Linux targets. The Arduino one is there to verify that the build works with all the required libraries, and the Linux build we can use for test automation with &lt;a href="https://github.com/flowbased/fbp-spec"&gt;fbp-spec&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To flash the actual devices you need the &lt;a href="https://www.arduino.cc/en/Main/Software"&gt;Arduino IDE&lt;/a&gt; and Node.js. Then use MicroFlo to generate the &lt;code class="language-plaintext highlighter-rouge"&gt;.ino&lt;/code&gt; file, and flash that to the device with the IDE. WiFi and MQTT settings can be tweaked in the &lt;a href="https://github.com/c-base/microflo-luftdaten/blob/master/secrets.example.h"&gt;secrets.h&lt;/a&gt; and &lt;a href="https://github.com/c-base/microflo-luftdaten/blob/master/config.h"&gt;config.h&lt;/a&gt; files.&lt;/p&gt;
&lt;h2 id="sensor-deployment"&gt;Sensor deployment&lt;/h2&gt;

&lt;p&gt;The recommended weatherproofing solution for these sensors is quite straightforward: place the hardware in a piece of drainage pipe with the ends turned downwards.&lt;/p&gt;

&lt;p&gt;Since we had two sensors, we decided to install one in the patio, and the other in the c-base main hall:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Particulate matter sensor in c-base main hall" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/luftdaten-sensor-mainhall.jpg" /&gt;&lt;/p&gt;

&lt;h2 id="working-with-the-sensor-data"&gt;Working with the sensor data&lt;/h2&gt;

&lt;p&gt;Once the sensor devices had been flashed, they became available in &lt;a href="https://github.com/c-base/c-flo"&gt;our MsgFlo setup&lt;/a&gt; and could be connected with other systems:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Particulate matter sensor in c-base main hall" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/luftdaten-sensor-msgflo.png" /&gt;&lt;/p&gt;

&lt;p&gt;In our case, we wanted to do two things with the data:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Log it in the c-base telemetry system to be &lt;a href="http://bergie.iki.fi/blog/nasa-openmct-iot-dashboard/"&gt;visualized with NASA OpenMCT&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Submit the data from the outdoor sensor to the &lt;a href="https://luftdaten.info/"&gt;luftdaten.info database&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first one was just a matter of adding &lt;a href="https://github.com/c-base/cbeam-telemetry-server/pull/61"&gt;couple of configuration lines&lt;/a&gt; to our OpenMCT server. For the latter, I built a &lt;a href="https://github.com/c-base/c-flo/blob/master/components/SendToLuftDaten.py"&gt;simple Python component&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our sensors have been tracking for a couple of days now. The public data can be seen in &lt;a href="https://www.madavi.de/sensor/graph.php?sensor=msgflo-00000042-sds011"&gt;the madavi service&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Readings from the c-base outdoor sensor" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/luftdaten-sensor-madavi.png" /&gt;&lt;/p&gt;

&lt;p&gt;We’ve &lt;a href="http://luftdaten.info/feinstaubsensor-bauen/#feinstaubsensor-konfiguration"&gt;submitted our sensor&lt;/a&gt; for inclusion in the luftdaten.info database, and hopefully soon there will be another covered area in the &lt;a href="http://berlin.maps.luftdaten.info/#13/52.5150/13.4211"&gt;Berlin air quality map&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img alt="luftdaten.info Berlin map" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/luftdaten-sensor-berlin.png" /&gt;&lt;/p&gt;

&lt;p&gt;If you’d like to build your own air quality sensor, the &lt;a href="https://luftdaten.info/en/construction-manual/"&gt;instructions on luftdaten.info&lt;/a&gt; are pretty comperehensive. Get the parts from your local electronics store or AliExpress, connect them together, flash the firmware, and be part of the public effort to track and improve air quality!&lt;/p&gt;

&lt;p&gt;Our &lt;a href="https://github.com/c-base/microflo-luftdaten"&gt;MicroFlo firmware&lt;/a&gt; is a great alternative if you want to do further analysis of the data yourself, or simply want to get the data on MQTT.&lt;/p&gt;</description><author>Henri Bergius</author><pubDate>Mon, 26 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bergie.iki.fi/blog/microflo-particulate-sensors/</guid></item><item><title>Suggestions added to Django manage.py</title><link>https://tomforb.es/blog/django-manage-suggestions/</link><description>My recently merged PR for ticket #28398 adds very simple ‘did you mean’ suggestions to Django’s manage.py command, which is the primary way of interacting with Django from the terminal. So in Django 2.1 this is what you will expect to see if you misspell a management command:...</description><author>Tom Forbes</author><pubDate>Sat, 24 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/django-manage-suggestions/</guid></item><item><title>asComponent: turn any JavaScript function into a NoFlo component</title><link>https://bergie.iki.fi/blog/ascomponent/</link><description>&lt;p&gt;Version 1.1 of &lt;a href="https://noflojs.org"&gt;NoFlo&lt;/a&gt; shipped this week with a new convenient way to write components. With the &lt;code class="language-plaintext highlighter-rouge"&gt;noflo.asComponent&lt;/code&gt; helper you can turn any JavaScript function into a well-behaved NoFlo component with minimal boilerplate.&lt;/p&gt;

&lt;p&gt;Usage of &lt;code class="language-plaintext highlighter-rouge"&gt;noflo.asComponent&lt;/code&gt; is quite simple:&lt;/p&gt;

&lt;div class="language-javascript highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;noflo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;noflo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;noflo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In this case we have a function that doesn’t take arguments. We detect this, and produce a component with a single “bang” port for invoking the function:&lt;/p&gt;

&lt;p&gt;&lt;img alt="Math.random as component" src="https://d2vqpl3tx84ay5.cloudfront.net/500x/ascomponent-result.png" /&gt;&lt;/p&gt;

&lt;p&gt;You can also amend the component with helpful information like a textual description and and icon:&lt;/p&gt;

&lt;div class="language-javascript highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;noflo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;noflo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;noflo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Generate a random number&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;random&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="Math.random with custom icon" src="https://d2vqpl3tx84ay5.cloudfront.net/500x/ascomponent-custom-icon.png" /&gt;&lt;/p&gt;

&lt;h2 id="multiple-inputs"&gt;Multiple inputs&lt;/h2&gt;

&lt;p&gt;The example above was with a function that does not take any arguments. With functions that accept arguments, each of them becomes an input port.&lt;/p&gt;

&lt;div class="language-javascript highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;noflo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;noflo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;findItemsWithId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;noflo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;findItemsWithId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="asComponent and multiple inports" src="https://d2vqpl3tx84ay5.cloudfront.net/500x/ascomponent-multiple-inports.png" /&gt;&lt;/p&gt;

&lt;p&gt;The function will be called when both input ports have a packet available.&lt;/p&gt;

&lt;h2 id="output-handling"&gt;Output handling&lt;/h2&gt;

&lt;p&gt;The &lt;code class="language-plaintext highlighter-rouge"&gt;asComponent&lt;/code&gt; helper handles three types of functions:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Regular synchronous functions: return value gets sent to &lt;code class="language-plaintext highlighter-rouge"&gt;out&lt;/code&gt;. Thrown errors get sent to &lt;code class="language-plaintext highlighter-rouge"&gt;error&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Functions returning a Promise: resolved promises get sent to &lt;code class="language-plaintext highlighter-rouge"&gt;out&lt;/code&gt;, rejected promises to &lt;code class="language-plaintext highlighter-rouge"&gt;error&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Functions taking a Node.js style asynchronous callback: &lt;code class="language-plaintext highlighter-rouge"&gt;err&lt;/code&gt; argument to callback gets sent to &lt;code class="language-plaintext highlighter-rouge"&gt;error&lt;/code&gt;, result gets sent to &lt;code class="language-plaintext highlighter-rouge"&gt;out&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this, it is quite easy to write wrappers for asynchronous operations. For example, to call an external REST API with the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API"&gt;Fetch API&lt;/a&gt;:&lt;/p&gt;

&lt;div class="language-javascript highlighter-rouge"&gt;&lt;div class="highlight"&gt;&lt;pre class="highlight"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;noflo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;noflo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getFlowhubStats&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.flowhub.io/stats&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;noflo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;asComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getFlowhubStats&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;How that you have this component, it is quick to do a graph utilizing it (&lt;a href="https://app.flowhub.io/#github/bergie/flowhubstats"&gt;open in Flowhub&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.flowhub.io/#github/bergie/flowhubstats"&gt;&lt;img alt="Example graph with asynchronous asComponent" src="https://d2vqpl3tx84ay5.cloudfront.net/800x/ascomponent-fetch-graph.png" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we get the BODY element of the browser runtime. When that has been loaded, we trigger the fetch component above. If the request succeeds, we process it through a string template to write a quick report to the page. If it fails, we grab the error message and write that.&lt;/p&gt;

&lt;h2 id="making-the-components-discoverable"&gt;Making the components discoverable&lt;/h2&gt;

&lt;p&gt;The default location for a NoFlo component is &lt;code class="language-plaintext highlighter-rouge"&gt;components/ComponentName.js&lt;/code&gt; inside your project folder. Add your new components to this folder, and NoFlo will be able to run them.&lt;/p&gt;

&lt;p&gt;If you’re using &lt;a href="https://flowhub.io/ide"&gt;Flowhub&lt;/a&gt;, you can also write the components in the integrated code editor, and they will be sent to the runtime.&lt;/p&gt;

&lt;p&gt;We’ve already updated the hosted NoFlo browser runtime to 1.1, so you can get started with this new component API right away.&lt;/p&gt;

&lt;h2 id="advanced-components"&gt;Advanced components&lt;/h2&gt;

&lt;p&gt;In many ways, asComponent is the inverse of the &lt;a href="http://bergie.iki.fi/blog/ascallback/"&gt;asCallback embedding feature&lt;/a&gt; we introduced a year ago: &lt;code class="language-plaintext highlighter-rouge"&gt;asComponent&lt;/code&gt; turns a regular JavaScript function into a NoFlo component; &lt;code class="language-plaintext highlighter-rouge"&gt;asCallback&lt;/code&gt; turns a NoFlo component (or graph) into a regular JavaScript function.&lt;/p&gt;

&lt;p&gt;If you need to work with more complex firing patterns, like combining streams or having control ports, you can of course still write regular &lt;a href="https://noflojs.org/documentation/components/#component-api"&gt;Process API&lt;/a&gt; components.&lt;/p&gt;

&lt;p&gt;The regular component API is quite a bit more verbose, but at the same time gives you full access to NoFlo APIs for dealing with manually controlled preconditions, state management, and creating &lt;a href="https://noflojs.org/documentation/components/#generator-components"&gt;generators&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;However, thinking about the hundreds of NoFlo components out there, most of them could be written much more simply with &lt;code class="language-plaintext highlighter-rouge"&gt;asComponent&lt;/code&gt;. This will hopefully make the process of developing NoFlo programs a lot more straightforward.&lt;/p&gt;

&lt;p&gt;Read more &lt;a href="https://noflojs.org/documentation/components/"&gt;NoFlo component documentation&lt;/a&gt; and &lt;a href="https://noflojs.org/api/AsComponent/"&gt;asComponent API docs&lt;/a&gt;.&lt;/p&gt;</description><author>Henri Bergius</author><pubDate>Fri, 23 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://bergie.iki.fi/blog/ascomponent/</guid></item><item><title>Scraping my Twitter Social Graph with Python and Selenium</title><link>https://www.swyx.io/scraping-my-twitter-social-graph-with-python-and-selenium--hn8</link><description>&lt;p&gt;Using python and selenium to find better follows on Twitter&lt;/p&gt;</description><author>swyx's site RSS Feed</author><pubDate>Mon, 19 Feb 2018 01:30:05 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/scraping-my-twitter-social-graph-with-python-and-selenium--hn8</guid></item><item><title>GitHub Shouldn't Allow Username Reuse</title><link>https://donatstudios.com/GithubsTotalSecurityFacepalm</link><description>&lt;p&gt;&lt;strong&gt;Update 2018-04-19&lt;/strong&gt; - GitHub has &lt;a href="https://blog.github.com/2018-04-18-new-tools-for-open-source-maintainers/#popular-repository-namespace-retirement"&gt;implemented some rules&lt;/a&gt; around retiring &amp;quot;namespaces&amp;quot;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;To prevent developers from pulling down potentially unsafe packages, we now retire the namespace of any open source project that had more than 100 clones in the week leading up to the owner’s account being renamed or deleted. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is a decent half step but I'd still love to see either permalinks or &lt;strong&gt;every&lt;/strong&gt; namespace of a user permanently retired once their account is deleted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 2018-02-10&lt;/strong&gt; In discussing this with people online, I’ve come to the conclusion that the bigger, more important  issue is lack of &lt;strong&gt;permalinks&lt;/strong&gt; to repository instances. Path reuse, rather than username reuse.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;There is a very popular tool for embedding data files into your Go binaries called &lt;code&gt;go-bindata&lt;/code&gt;.  Several days ago however the user who ran it, &amp;quot;Jim Teeuwen&amp;quot; (&lt;a href="https://web.archive.org/web/20150609210529/https://github.com/jteeuwen"&gt;wayback machine&lt;/a&gt;), completely disappeared from the internet – deleting his GitHub account and personal domain in the process.&lt;/p&gt;
&lt;p&gt;While this is within his rights to do, this broke a dependency many people had within their projects.&lt;/p&gt;
&lt;p&gt;To fix this, some users of the project recreated the &lt;strong&gt;account&lt;/strong&gt; and the repository based on a fork of the project. &lt;/p&gt;
&lt;p&gt;They have an official announcement/disclosure here:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/jteeuwen/go-bindata/issues/5"&gt;https://github.com/jteeuwen/go-bindata/issues/5&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;At the very least they are being honest about it.&lt;/p&gt;
&lt;p&gt;The fact that they were &lt;strong&gt;allowed&lt;/strong&gt; to do this however represents a fundamental flaw in GitHub's security model.&lt;/p&gt;
&lt;p&gt;Usernames, once deleted, should &lt;strong&gt;never&lt;/strong&gt; be allowed to be valid again. Many sites including Google do it this way. &lt;/p&gt;
&lt;p&gt;Allowing username reuse completely breaks any trust that what I pull is what it claims to be.&lt;/p&gt;
&lt;p&gt;What if this user had been malicious? It may have taken a while before someone actually noticed this wasn't the original user and the code was doing something more than it claimed to.&lt;/p&gt;
&lt;p&gt;While Go's &lt;code&gt;go get&lt;/code&gt; functionality is no doubt naive and just pulls the head of a repository, this is not exclusively Go's problem as this affects any &lt;strong&gt;package manager&lt;/strong&gt; that runs on tags. Simply tag malicious changes beyond the current release and it would be deployed to many users likely with little actual review.&lt;/p&gt;
&lt;p&gt;This should not be possible. This is scary and should be fixed.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many people are arguing that this is the developers fault or the package managers fault. I do not agree, but as far as I see it that doesn't matter anyway.  The simple fact of the matter is that it &lt;em&gt;is&lt;/em&gt; being used like that, like it or not, and the simplest and I argue most correct fix is for GitHub to prevent the issue.&lt;/p&gt;
&lt;p&gt;I think another good option would be GitHub offering permalinks to repos, such that if they were deleted and recreated the pathing would change.&lt;/p&gt;
&lt;p&gt;It affects &lt;strong&gt;not only package managers&lt;/strong&gt; and programs and software, but humans. Humans navigating GitHub. I have no way to tell while navigating the site if a project is the original or a charade.  That is a problem.&lt;/p&gt;
&lt;p&gt;As for the title change, I agreed with Hacker News that the original was a bit hyperbolic. I have a tendency to resort to hyperbole to get my emotional point across - and it doesn't always read correctly on the internet.&lt;/p&gt;</description><author>Donat Studios</author><pubDate>Sat, 10 Feb 2018 05:19:29 GMT</pubDate><guid isPermaLink="true">https://donatstudios.com/GithubsTotalSecurityFacepalm</guid></item><item><title>A records on top level domains</title><link>https://captnemo.in/blog/2018/02/09/tld-a-records/</link><description>&lt;p&gt;Re-ran the same scan as http://blog.towo.eu/a-records-on-top-level-domains/&lt;/p&gt;

&lt;p&gt;Scan run from &lt;code class="language-plaintext highlighter-rouge"&gt;AS9498&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Results:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;TLD&lt;/th&gt;
      &lt;th&gt;IP&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;ai&lt;/td&gt;
      &lt;td&gt;209.59.119.34&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;android&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;arab&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;cal&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;chrome&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;cm&lt;/td&gt;
      &lt;td&gt;195.24.205.60&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dclk&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;dk&lt;/td&gt;
      &lt;td&gt;193.163.102.58&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;drive&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;etisalat&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;gg&lt;/td&gt;
      &lt;td&gt;87.117.196.80&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;gle&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;guge&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;hangout&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;je&lt;/td&gt;
      &lt;td&gt;87.117.196.80&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;nexus&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pa&lt;/td&gt;
      &lt;td&gt;168.77.8.43&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;play&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;pn&lt;/td&gt;
      &lt;td&gt;80.68.93.100&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;politie&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;sport&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;tk&lt;/td&gt;
      &lt;td&gt;217.119.57.22&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;uz&lt;/td&gt;
      &lt;td&gt;91.212.89.8&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;ws&lt;/td&gt;
      &lt;td&gt;64.70.19.33&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;谷歌&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;218.100.84.27&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;202.170.80.40&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;мон&lt;/td&gt;
      &lt;td&gt;180.149.98.78&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;اتصالات&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;政府&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;عرب&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;招聘&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;グーグル&lt;/td&gt;
      &lt;td&gt;127.0.53.53&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: An automatically updated version of this is available at https://captnemo.in/tld-a-record/&lt;/p&gt;</description><author>Nemo's Home</author><pubDate>Fri, 09 Feb 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://captnemo.in/blog/2018/02/09/tld-a-records/</guid></item><item><title>What Happens When A User Edits A Post on Dev.to?</title><link>https://www.swyx.io/what-happens-when-a-user-edits-a-post-on-devto-a58</link><description>&lt;hr /&gt;</description><author>swyx's site RSS Feed</author><pubDate>Sat, 03 Feb 2018 21:25:54 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/what-happens-when-a-user-edits-a-post-on-devto-a58</guid></item><item><title>Postgres hidden gems</title><link>/2018/01/31/Postgres-hidden-gems/</link><description>&lt;p&gt;Postgres has a rich set of features, even when working everyday with it you may not discover all it has to offer. In hopes of learning some new features that I didn&amp;rsquo;t know about myself as well as seeing what small gems people found joy in I tweeted out to see what people came back from. The response was impressive, and rather than have it lost into ether of twitter I&amp;rsquo;m capturing some of the responses here along with some resources many of the features.&lt;/p&gt;
&lt;!-- raw HTML omitted --&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/listrophy"&gt;@listrophy&lt;/a&gt; - &lt;code&gt;$ brew postgresql-update database&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Though personally I prefer Postgres.app ;)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/pat_shaugnessy"&gt;@pat_shaugnessy&lt;/a&gt; - ltree
&lt;ul&gt;
&lt;li&gt;Pat has a great post that walks through &lt;a href="http://patshaughnessy.net/2017/12/13/saving-a-tree-in-postgres-using-ltree"&gt;ltree&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/billyfung"&gt;@billyfung&lt;/a&gt; - citext
&lt;ul&gt;
&lt;li&gt;A really handy datatype for case insensitive text&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/eeeebbbbrrrr"&gt;@eeeebbbbrrrr&lt;/a&gt; - date math with intervals
&lt;ul&gt;
&lt;li&gt;I couldn&amp;rsquo;t agree more on this one, &lt;a href="/2017/06/08/working-with-time-in-postgres/"&gt;working with time in Postgres&lt;/a&gt; is the easiest time I&amp;rsquo;ve every had&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/DataMiller"&gt;@DataMiller&lt;/a&gt; - The jsonb datatype and lateral joins
&lt;ul&gt;
&lt;li&gt;I&amp;rsquo;d argue it&amp;rsquo;s hard to claim now JSONB is a hidden gem, but &lt;a href="https://blog.heapanalytics.com/postgresqls-powerful-new-join-type-lateral/"&gt;lateral joins&lt;/a&gt; are certain a great one&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/ideasasylum"&gt;@ideasasylum&lt;/a&gt; - row_number() over(partition &lt;a href="http://orders.site"&gt;http://orders.site&lt;/a&gt;_id order by orders.created_at)
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://robots.thoughtbot.com/postgres-window-functions"&gt;Window functions&lt;/a&gt; are definitely a handy feature
was my hidden (to me) discovery this week&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/franckverrot"&gt;@franckverrot&lt;/a&gt; - Index access method, and custom FDWs&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/jonjensen0"&gt;@jonjensen0&lt;/a&gt; - &lt;a href="https://www.postgresql.org/docs/9.5/static/functions-srf.html"&gt;Set-returning functions&lt;/a&gt; and custom aggregate functions can be very helpful.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/ascherbaum"&gt;@ascherbaum&lt;/a&gt; - psql -x
&lt;ul&gt;
&lt;li&gt;Psql is indeed awesome and can be &lt;a href="http://www.craigkerstiens.com/2013/02/13/How-I-Work-With-Postgres/"&gt;well tuned&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/Abstr_ct"&gt;@Abstr_ct&lt;/a&gt; - The fact that the docs are fantastic and all hidden gems are actually readily available. Oh, and pl/brainfuck obviously&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/Halpin_IO"&gt;@Halpin_IO&lt;/a&gt; - Subnetting and network operations&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/jkatz05"&gt;@jkatz05&lt;/a&gt; - Replication slots, both physical and logical. They&amp;rsquo;ve made setting up replication infinitely easier. And range types. Because they&amp;rsquo;re awesome.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/petereisentraut"&gt;@petereisentraut&lt;/a&gt; - Unicode table borders&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/_avichalp"&gt;@_avichalp&lt;/a&gt; Notify/listen&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/simonw"&gt;@simonw&lt;/a&gt; - The fact that &lt;a href="https://www.citusdata.com/blog/2017/10/17/tour-of-postgres-index-types/"&gt;GIN indices&lt;/a&gt; can make LIKE queries run fast even if the % isn&amp;rsquo;t just at the end of the string&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/javisantana"&gt;@javisantana&lt;/a&gt; - it has a statistics system to plan queries that can be used by the user when accuracy does not matter, for example, use &amp;ldquo;explain select * from table&amp;rdquo; to replace count() or use &amp;ldquo;_postgis_selectivity&amp;rdquo; to know how many points fall into a bbox.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/l_avrot"&gt;@l_avrot&lt;/a&gt; - The fact that we can use vim editor in psql&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/mashd"&gt;@mashd&lt;/a&gt; - Logical decoding for change data capture.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/4thdoctor_scarf"&gt;@4thdoctor_scarf&lt;/a&gt; - the MVCC. If I had a penny per each time I&amp;rsquo;ve explained how really works, I&amp;rsquo;ll be a millionaire now :)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/docteur_klein"&gt;@docteur_klein&lt;/a&gt; - \timing in psql&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/thibaut_barrere"&gt;@thibaut_barrere&lt;/a&gt; - From times to times I find foreign data wrapper with CSV files very helpful (&amp;amp; easy to setup with Ruby&amp;rsquo;s Sequel library) &lt;a href="https://gist.github.com/thbar/0093ee54c5a61aa5a0c5a4737fc3bd45"&gt;https://gist.github.com/thbar/0093ee54c5a61aa5a0c5a4737fc3bd45&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/steve_touw"&gt;@steve_touw&lt;/a&gt; - &lt;a href="http://www.craigkerstiens.com/2016/09/11/a-tour-of-fdws/"&gt;Foreign data wrappers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/roimartinez_gis"&gt;@roimartinez_gis&lt;/a&gt; - Clearly aggregate functions make live very simple :) .&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/whalesalad"&gt;@whalesalad&lt;/a&gt; - select where datetime &amp;gt; yesterday and other natural language time queries.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/pwramsey"&gt;@pwramsey&lt;/a&gt; - At the hacker level: hooks. So many cool hooks, and finding them, a bit of an easter egg hunt.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/pwramsey"&gt;@pwramsey&lt;/a&gt; - At the user level: the quality and breadth of tsearch still feels radically under appreciated; same for ranges.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/TomCiopp"&gt;@TomCiopp&lt;/a&gt; - PostGIS / PgRouting&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/peterbe"&gt;@peterbe&lt;/a&gt; - psql -l&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/jbrancha"&gt;@jbrancha&lt;/a&gt; - In psql, setting ‘\x auto’ so that wide table results get displayed vertically!&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.twitter.com/westermanndanie"&gt;@westermanndanie&lt;/a&gt; - &lt;code&gt;\watch&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Well that was quite the list. And I&amp;rsquo;m sure we&amp;rsquo;ve only scratched the surface. Have something not on the list that you feel like classifies as a hidden gem? &lt;a href="https://www.twitter.com/craigkerstiens"&gt;Lets hear about it&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;If you&amp;rsquo;re looking for a deeper resource on Postgres I recommend the book &lt;a href="https://theartofpostgresql.com/?affiliate=cek"&gt;The Art of PostgreSQL&lt;/a&gt;. It is by a personal friend that has aimed to create the definitive guide to Postgres, from a developer perspective. If you use code CRAIG15 you&amp;rsquo;ll receive 15% off as well.&lt;/em&gt;&lt;/p&gt;</description><author>CRAIG KERSTIENS</author><pubDate>Wed, 31 Jan 2018 22:55:56 GMT</pubDate><guid isPermaLink="true">/2018/01/31/Postgres-hidden-gems/</guid></item><item><title>Interview with the D Language Blog: BSDScheme</title><link>http://notes.eatonphil.com/project-highlight-bsdscheme.html</link><description>&lt;p&gt;This is an external post of mine. Click
&lt;a href="https://dlang.org/blog/2018/01/20/project-highlight-bsdscheme/"&gt;here&lt;/a&gt;
if you are not redirected.&lt;/p&gt;</description><author>Notes on software development</author><pubDate>Sat, 20 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/project-highlight-bsdscheme.html</guid></item><item><title>Theory of constraints</title><link>https://smcleod.net/2018/01/theory-of-constraints/</link><description>&lt;h3 id="a-chain-is-no-stronger-than-its-weakest-link"&gt;&amp;ldquo;A chain is no stronger than its weakest link&amp;rdquo;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Any improvement made anywhere besides the bottleneck is an illusion.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any improvement made after the bottleneck is useless because it will always remain starved waiting for work from the bottleneck.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Any improvement made before the bottleneck merely results in more ‘work&amp;rsquo; piling up at the bottleneck.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;em&gt;Identify&lt;/em&gt; the system&amp;rsquo;s constraint(s) (that which prevents the organisation from obtaining more of the goal in a unit of time)&lt;/li&gt;
&lt;li&gt;Decide how to &lt;em&gt;exploit&lt;/em&gt; the system&amp;rsquo;s constraint(s) (how to get the most out of the constraint)&lt;/li&gt;
&lt;li&gt;Subordinate everything else to the above decision (&lt;em&gt;align&lt;/em&gt; the whole system or organization to support the decision made above)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Elevate&lt;/em&gt; the system&amp;rsquo;s constraint(s) (make other major changes needed to increase the constraint&amp;rsquo;s capacity)&lt;/li&gt;
&lt;li&gt;Warning! If in the previous steps a constraint has been broken, go back to step 1, but do not allow inertia to cause a system&amp;rsquo;s constraint.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h3 id="references"&gt;References&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.amazon.com/The-Phoenix-Project-Helping-Business/dp/0988262592"&gt;The Phoenix Project&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Theory_of_constraints"&gt;Wikipedia - Theory of Constraints&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description><author>smcleod.net</author><pubDate>Wed, 17 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://smcleod.net/2018/01/theory-of-constraints/</guid></item><item><title>Hello, I am making a modern fullstack JS tutorial livestream. What questions do you have for me?</title><link>https://www.swyx.io/hello-i-am-making-a-modern-fullstack-js-tutorial-what-questions-do-you-have-for-me-dg3</link><description>&lt;hr /&gt;</description><author>swyx's site RSS Feed</author><pubDate>Tue, 16 Jan 2018 08:26:44 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/hello-i-am-making-a-modern-fullstack-js-tutorial-what-questions-do-you-have-for-me-dg3</guid></item><item><title>Goodby Simple, hello Gatsby</title><link>https://tomforb.es/blog/goodby-simple-hello-gatsby/</link><description>Many years ago, inspired by a blogging platform called Svbtle , I built a clone called Simple. It was pretty simple - just a minimal Flask app backed by a Sqlite database, but had some cool features. You could log in with Mozilla’s Persona (RIP), edit posts using an in-browser editor and drag ‘n’ dr...</description><author>Tom Forbes</author><pubDate>Tue, 16 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://tomforb.es/blog/goodby-simple-hello-gatsby/</guid></item><item><title>First few hurdles writing a Scheme interpreter</title><link>http://notes.eatonphil.com/first-few-hurdles-writing-a-scheme-interpreter.html</link><description>&lt;p&gt;I started working on &lt;a href="https://github.com/eatonphil/bsdscheme"&gt;BSDScheme&lt;/a&gt; last October, inspired to get back
into language implementation after my coworker built &lt;a href="https://github.com/briansteffens/bshift"&gt;bshift&lt;/a&gt;, a
compiler for a C-like language. BSDScheme is an interpreter for a
(currently small subset of) Scheme written in D. It implements a few
substantial primitive &lt;a href="https://github.com/eatonphil/bsdscheme/blob/c49bb14182f04682a5cda4dd224b853b4fc92e92/src/runtime.d#L422"&gt;functions&lt;/a&gt; (in under 1000 LoC!). It uses the
same test framework bshift uses, &lt;a href="https://github.com/briansteffens/btest"&gt;btest&lt;/a&gt;. I'm going to expand here
on some notes I wrote in a &lt;a href="https://www.reddit.com/r/scheme/comments/7nvd1y/my_small_scheme_implementation_in_d/"&gt;post&lt;/a&gt; on Reddit on some issues I faced
during these first few months developing BSDSCheme.&lt;/p&gt;
&lt;p&gt;Before I get too far, here is a simple exponent function running in
BSDScheme. It demonstates a few of the basic builtin primitives and
also integers being upgraded to D's &lt;a href="https://dlang.org/phobos/std_bigint.html"&gt;std.bigint&lt;/a&gt; when an integer
operation produces an integer unable to fit in 64 bits. (See the
&lt;a href="https://github.com/eatonphil/bsdscheme/blob/b202e8b5a24fe4281a06e39241f2be3cd51720fc/src/runtime.d#L99"&gt;times&lt;/a&gt; and &lt;a href="https://github.com/eatonphil/bsdscheme/blob/b202e8b5a24fe4281a06e39241f2be3cd51720fc/src/runtime.d#L63"&gt;plus&lt;/a&gt; guards for details; see the &lt;a href="https://github.com/eatonphil/bsdscheme/tree/master/examples"&gt;examples&lt;/a&gt;
directory for other examples.)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;examples/recursion.scm
&lt;span class="o"&gt;(&lt;/span&gt;define&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;exp&lt;span class="w"&gt; &lt;/span&gt;base&lt;span class="w"&gt; &lt;/span&gt;pow&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;pow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;*&lt;span class="w"&gt; &lt;/span&gt;base&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;exp&lt;span class="w"&gt; &lt;/span&gt;base&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;pow&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)))))&lt;/span&gt;

&lt;span class="o"&gt;(&lt;/span&gt;display&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;exp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;64&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;newline&lt;span class="o"&gt;)&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;./bin/bsdscheme&lt;span class="w"&gt; &lt;/span&gt;examples/exp.scm
&lt;span class="m"&gt;18446744073709551616&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The first big correction I made was to the way values are represented
in memory. I originally implemented BSDScheme's value representation
as a &lt;a href="https://github.com/eatonphil/bsdscheme/pull/3/files#diff-653d5ccdaa287f13a3b2d964da52ab4aL284"&gt;struct&lt;/a&gt; with a pointer to each possible value type. This
design was simple to begin with but space-inefficient. I modelled a
&lt;a href="https://github.com/eatonphil/bsdscheme/pull/3"&gt;redesign&lt;/a&gt; after the &lt;a href="https://wiki.call-cc.org/man/4/Data%20representation"&gt;Chicken Scheme&lt;/a&gt; data representation. It
uses a struct with &lt;a href="https://github.com/eatonphil/bsdscheme/pull/3/files#diff-c586618fe7ea7c64340046e89fd82621R14"&gt;two fields&lt;/a&gt;, header and data. Both fields are
word-size integers (currently hard-coded as 64 bits). The header
stores type and length information and the data stores data.&lt;/p&gt;
&lt;p&gt;In this representation, simple types (integers &amp;lt; 2^63, booleans,
characters, etc.) take up only 128 bits. The integers, booleans, etc.
are placed directly into the 64 bit data field. Other types (larger
integers, strings, functions, etc) use the data field to store a
pointer to memory allocated in the heap. Getting the conversion of
these complex types right was the trickiest part of this data
representation effort... lots of void-pointer conversions.&lt;/p&gt;
&lt;p&gt;The next big fix I made was to simplify the way generic functions
dealt with their arguments. Originally I passed each function its
arguments un-evaluated and left it up to each function to evaluate its
arguments before operating on them. While there was nothing
intrinsically wrong with this method, it was overly complicated and
bug-prone. I refactored the builtin functions into two groups:
&lt;a href="https://github.com/eatonphil/bsdscheme/blob/c49bb14182f04682a5cda4dd224b853b4fc92e92/src/runtime.d#L422"&gt;normal&lt;/a&gt; functions and &lt;a href="https://github.com/eatonphil/bsdscheme/blob/c3286df73a32da657e780db8f33e845c9f806a9d/src/runtime.d#L435"&gt;special&lt;/a&gt; functions. Normal function
arguments are &lt;a href="https://github.com/eatonphil/bsdscheme/blob/c3286df73a32da657e780db8f33e845c9f806a9d/src/runtime.d#L399"&gt;evaluated&lt;/a&gt; before sending the arguments S-expression
to the function. Special functions receive the arguments S-expression
verbatim so they can decide what / when to evaluate.&lt;/p&gt;
&lt;p&gt;The last issue I'll talk about in this post was dealing with the AST
representation. When I started out, the easiest way to get things
working was to have an AST representation completely separate from the
representation of BSDScheme values. This won't get you far in
Scheme. In order to (eventually) support macros (and in the meantime
support eval), the AST representation would have to make use of the
value representation. This was the most complicated and confusing
issue so far in BSDScheme. With the switch to recursive data
structures, it was hard to know if an error occurred because I parsed
incorrectly, or recursed over what I parsed incorrectly, or even if I
was printing out what I parsed incorrectly. After some embarrassing
pain, I got all the &lt;a href="https://github.com/eatonphil/bsdscheme/pull/5"&gt;pieces in place&lt;/a&gt; after a month and it set me
up to easily support converting my original interpret function into a
generic eval function that I could expose to the language like any
other special function.&lt;/p&gt;
&lt;p&gt;One frustrating side-effect of this AST conversion is that since the
parsing stage builds out trees using the internal value
representation, the parsing stage is tied to the interpreter. From
what I can tell, this basically means I have to revert back to some
intermediate AST representation or throw away the parser to support a
compiler backend.&lt;/p&gt;
&lt;p&gt;Next steps in BSDScheme include converting all the examples into
tests, combining the needlessly split out lexing and parsing stage
into a single read function that can be exposed into the language,
fleshing out R7RS library support, and looking more into LLVM as a
backend.&lt;/p&gt;
&lt;p&gt;&lt;blockquote class="twitter-tweet"&gt;&lt;p dir="ltr" lang="en"&gt;Wrote a full post on the first few hurdles faced writing a Scheme interpreter in D &lt;a href="https://t.co/Cyjy7pk3OB"&gt;https://t.co/Cyjy7pk3OB&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/scheme?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#scheme&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/schemelang?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#schemelang&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/lisp?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#lisp&lt;/a&gt; &lt;a href="https://twitter.com/hashtag/dlang?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#dlang&lt;/a&gt;&lt;/p&gt;&amp;mdash; Phil Eaton (@phil_eaton) &lt;a href="https://twitter.com/phil_eaton/status/951091952740651008?ref_src=twsrc%5Etfw"&gt;January 10, 2018&lt;/a&gt;&lt;/blockquote&gt; &lt;/p&gt;</description><author>Notes on software development</author><pubDate>Wed, 10 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">http://notes.eatonphil.com/first-few-hurdles-writing-a-scheme-interpreter.html</guid></item><item><title>How To Google Your Errors</title><link>https://www.swyx.io/how-to-google-your-errors-2l6o</link><description>&lt;hr /&gt;</description><author>swyx's site RSS Feed</author><pubDate>Thu, 04 Jan 2018 19:32:12 GMT</pubDate><guid isPermaLink="true">https://www.swyx.io/how-to-google-your-errors-2l6o</guid></item><item><title>How and why we teach non-engineers to use GitHub at Thread</title><link>https://danpalmer.me/2018-01-04-teaching-non-engineers-how-to-contribute-code/</link><description>At Thread one of our core beliefs is that technology allows for great change. This is important to our product, but it’s also important to how we work internally.
Because of this way of working, we try to represent everything in data—products, measurements, styles, suppliers, locations in our warehouse, support ticket resolutions, and many more things that you’d never even think about.
All of these data models come with a cost of needing a way for those in the company who use them to maintain the data.</description><author>Dan Palmer</author><pubDate>Thu, 04 Jan 2018 02:00:00 GMT</pubDate><guid isPermaLink="true">https://danpalmer.me/2018-01-04-teaching-non-engineers-how-to-contribute-code/</guid></item></channel></rss>